Java Generics casts strangely

  • A+

I am using java 8.

I recently came across this:

public class Test {     public static void main(String[] args) {         String ss = "" + (Test.<Integer>abc(2));         System.out.println(Test.<Integer>abc(2));     }     public static <T> T abc(T a) {         String s = "adsa";         return (T) s;     } } 

This does not throw a java.lang.ClassCastException. Why is that?

I always thought + and System.out.println calls toString. But when I try to do that it throws an Exception as expected.

String sss = (Test.<Integer>abc(2)).toString(); 


It doesn't throw a ClassCastException because all generic type information is stripped from the compiled code (a process called type erasure). Basically, any type parameter is replaced by Object. That's why the first version works. It's also why the code compiles at all. If you ask the compiler to warn about unchecked or unsafe operations with the -Xlint:unchecked flag, you'll get a warning about an unchecked cast in the return statement of abc().

With this statement:

String sss = (Test.<Integer>abc(2)).toString(); 

the story is a bit different. While the type parameter T is replaced by Object, the calling code gets translated into byte code that explicitly casts the result to Integer. It is as if the code were written with a method with signature static Object abc(Object) and the statement were written:

String sss = ((Integer); 

That is, not only does the cast inside abc() go away due to type erasure, a new cast is inserted by the compiler in the calling code. This cast generates a ClassCastException at run time because the object returned from abc() is a String, not an Integer.

Note that the statement

String ss = "" + (Test.<Integer>abc(2)); 

doesn't require a cast because the compiler translates it into something that might have been written:

String ss = "" + String.valueOf(Test.<Integer>abc(2)); 

The compiler is smart enough to recognize that no cast is needed for this code.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: