Reputation: 3589
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
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
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