Consider below code and the output in Eclipse 4.5.0 & javac(1.8) .
I know it is due to the type erasure in runtime, but why the second one still output data even it is declared as List of Integer, I also checked with javap, checkcast bytecode is only inserted in the third output .
My questions are :
is it a bug ?
How the javac determine where to insert the "cast" ?
public static void main(String[] args){ List<String> a = Arrays.asList("abc","def"); List<Integer> b = (List<Integer>)(List<?>)a; System.out.println(b.size()); --output 2 System.out.println(b.get(1)); ---output "def" System.out.println(b.get(1).getClass()); --error in type cast
EDIT
Checked the answer below and the When is generic return value of function casted after type erasure? , quite similar with my case. If we add the answer from this What is meant by "the erasure of the static type of the expression on which it is called" in the getClass() docs?, then it will be much clear about the "cast" rule.
The compiler can determine where to insert the cast and ensure type safety.
My first case is fine since it will return int anyway.
Second case is fine since the println expect Object. so no cast is needed to ensure type safety.
Thrid case is not since the getClass() is expected to return the Class which is the static type of b.get(1) according to JLS. So the cast is inserted and get type cast error.
As @newacct said , "you should not rely on the compiler to decide either way" (when there is alternative choice and also ensure type safety ,the 2nd case here).