Being confused by Java generics requires a cast
I'm confused about the following code:
import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class GenericsTest<T extends List> { public void foo() { T var = (T) new LinkedList(); } public static void main(String[] args) { GenericsTest<ArrayList> gt1 = new GenericsTest<ArrayList>(); gt1.foo(); System.out.println("Done"); } }
Whatever the type parameter I pass to the constructor, t's runtime type seems to be Java util. List.
So why does the compiler need to convert to t when allocating var? Shouldn't it know at compile time that LinkedList can be assigned to list?
I understand that the code is fake, and I understand why it works at runtime, even if it doesn't look like it should The part that puzzles me is why the compiler requires me to type (T) when making assignments? However, if there is no forgery, it can be compiled well
Presumably, the compiler understands erasure It seems that the compiler should be able to compile code without casting
Solution
Asked the poster in the comment,
The cast won't fail But the compiler warns that this code will set up a time bomb to explode elsewhere in ClassCastException
In this example, there is no reason to use generics because the API does not use type variable T. please see a more real generic application
public class GenericsTest<T extends List> { 3 public T foo() { 4 T var = (T) new LinkedList(); 5 return var; 6 } 8 public static void main(String... argv) { 9 GenericsTest<ArrayList> gt1 = new GenericsTest<ArrayList>(); 10 gt1.foo(); 11 System.out.println("Test one okay"); 12 ArrayList<?> list = gt1.foo(); 13 System.out.println("Test two okay"); 14 } }
Throw ClassCastException on line 12 ClassCastException, no cast? The calling code is completely correct The invalid cast (Bug) is on line 4 of the calling method But this exception was made at a certain time and place
The purpose of Java generics is to ensure that code is type safe If all code is compiled without the "unchecked" warning, it is guaranteed that ClassCastException will not be thrown at run time However, if the library you rely on is not written correctly, as in this example, the promise will be broken