I know this question has been asked multiple times before but I'm looking for an answer based on type erasure.
Why does the compiler give an error on adding Integer
to ArrayList<String>
? I want to understand this by type erasure and byte code of add
method in ArrayList
.
Even though type erasure means that at execution time the VM can't distinguish between an ArrayList<String>
and an ArrayList<Integer>
(they're both just instances of ArrayList
) the compiler does know about the type argument, and knows what's safe.
So if you have:
ArrayList<Integer> integers = new ArrayList<Integer>();
integers.add("foo");
then the compile-time type of integers
is ArrayList<Integer>
, and any operations performed on integers
will be checked with that in mind. The only add
calls in ArrayList
are
add(E e)
add(int index, E e)
Now there's no conversion from String
to Integer
, so neither of those overloads is applicable for the call integers.add("foo")
, hence the compile-time error.
Basically, generics provide two things:
Integer
references, the compiler won't let you add a String
reference to itSimplicity in terms of casts - when a method of a class with a type parameter T
returns a value of type T
and the compiler knows what that T
is, it can insert an appropriate cast from the erased type (often Object
) to the type argument. That's how:
List<Integer> integers = getListFromSomewhere();
Integer x = integers.get(0);
works - the compiler adds a cast in the calling code. (That cast is still checked at execution time.)
See more on this question at Stackoverflow