Jurgen Camilleri
Jurgen Camilleri

Reputation: 3589

Why does ArrayList<E> constructor allow a raw ArrayList parameter

Why does this code compile:

ArrayList strings = new ArrayList();
strings.add("s1");
strings.add("s2");

ArrayList<Integer> numbers = new ArrayList<Integer>(strings);

Given that the constructor in question expects a Collection<? extends E> where E in this case is Integer? How are objects contained in the raw type ArrayList a subclass of E? Or is there some hidden compiler magic that allows this for legacy purposes?

Upvotes: 2

Views: 651

Answers (2)

Viet
Viet

Reputation: 3409

Check the ArrayList constructor:

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

The elementData is array of object:

transient Object[] elementData;

So new ArrayList(Collection<? extends E> c) will accept all Collection, don't care E type

It will throw ClassCastExceptionwhen when we use it :

Integer i= numbers.get(1);

Upvotes: 2

actc
actc

Reputation: 682

The compiler should give you this warning:

Type safety: The expression of type ArrayList needs unchecked conversion to conform to Collection<? extends Integer>

saying that there is something wrong with the given argument (strings).

You also should get this exception when trying to run the code:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

The reason you get no compile error is that the ArrayList strings is not defined correctly, you omitted the type String. So the compile may only guess that there is something worng. Change your code to

ArrayList<String> strings = new ArrayList<String>();

and you'll get the compile error

The constructor ArrayList<Integer>(ArrayList<String>) is undefined

Upvotes: 1

Related Questions