Here's a code snippet:
import java.util.*;
class Test
{
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
addToList(list);
Integer i = list.get(0); //#1 fails at run-time
String s = list.get(0); //#2 fails at compile-time
list.get(0); //#3 works fine
System.out.println(list.get(0)); //#4 works fine, prints "string"
}
static void addToList(List list){
list.add("string");
}
}
I understand why is it possible to insert an object of String class in parametrized List.
It seems like I understand why code marked with #1 and #2 fails.
But why do #3 and #4 work? As far as I understand, the compiler adds appropriate casts after type-erasure, so when I call list.get(0), this method should return an Object previously casted to Integer. So why there is no ClassCastException occures at #3 and #4 at run-time?
The #3 works because the object returned by get(int) is ignored. Whatever is stored at position 0 is returned, but since there is no cast, no error happens.
The #4 works fine for the same reason: the object produced by get(0) is treated like java.lang.Object subclass in println, because toString is called. Since toString() is available for all Java objects, the call completes without an error.