ConceptDifficulty: Intermediate1 min

What Is Left of List<String> by the Time the Program Runs

Two variables, declared with different type arguments, and a comparison of their classes that says they are the same.

java
List<String> a = new ArrayList<>();
List<Integer> b = new ArrayList<>();

System.out.println(a.getClass() == b.getClass());
text
true

Type arguments are checked by the compiler and then erased. The bytecode contains one ArrayList class, holding Object references, exactly as it did before generics existed.

What the compiler does and what the runtime sees
WrittenAt compile timeAt runtime
List<String>A list that only accepts stringsA list
refs.get(0)Produces a StringProduces an Object, cast to String
T in a generic classA real typeObject

Erasure was chosen so that code written before Java 5 kept running unchanged on the same virtual machine. It worked, and the price is paid by every strange generics rule you will meet.

So when the compiler refuses something about generics that looks perfectly reasonable, the reason is nearly always that the information you are relying on is gone by the time it would be needed.