0

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.

3 Answers 3

7

This has nothing to do with type erasure or byte code. The compiler gives you this error before it erases the generic type parameters and generates the byte code.

When adding an Integer to an ArrayList<String>, the compiler simply gives you an error because an Integer is not a sub-class of String.

Generics simply add a layer of type safety in compile time. If you would use raw ArrayList instead of ArrayList<String>, you would be able to add both Strings and Integers to your ArrayList. However, the generated byte code is the same regardless of whether you used ArrayList or ArrayList<String>.

Sign up to request clarification or add additional context in comments.

3 Comments

What I have read is erasure refers to replacing Object with generic Type so both of them are subclasses of Object
but you declare your ArrayList with String, now the compiler know it, if the compiler wouldn't give you an error, then it would be crash at runtime with an ClasscastExcpetion
@user2653926 But erasure happens only if the code passes compilation. If it fails to pass compilation, no byte code is generated, and no erasure takes place.
4

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.)

Comments

0

Let's start with a small example (note this uses raw types; and they are evil),

public static void main(String[] args) {
    List<String> strings = Arrays.asList("Hello");
    List<Integer> al = new ArrayList(strings);
    for (Integer v : al) {
        System.out.println(v);
    }
}

It compiles. If we run it we get

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at com.stackoverflow.Example.main(Example.java:11)

Because String is not Integer. We can examine the bytecode with javap -v

    35: invokeinterface #37,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
    40: checkcast     #43                 // class java/lang/Integer
    43: astore_3
    44: getstatic     #45                 // Field java/lang/System.out:Ljava/io/PrintStream;

And see that the cast fails on the line numbered 40. Generic types are for compile time type checking, at run-time (almost) everything is an Object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.