Compile time error when adding an Integer to a generic ArrayList of String

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.

Jon Skeet
people
quotationmark

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:

  • Compile-time safety to avoid this sort of broken code; if you've said that a list should only contain Integer references, the compiler won't let you add a String reference to it
  • Simplicity 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.)

people

See more on this question at Stackoverflow