Take a look at the following:
|
|
This compiles and executes. It results in a list containing one entry:
|
|
That one entry is an int[]
- our original numbers
primitive int
array.
You can create a List<int[]>
in Java - but that is not the type we specified. We specified List<Integer>
. What happened? How did we manage to place an int[]
into a list of type Integer
?
What’s worse, we don’t find out about this until we try to access the list - for example:
|
|
The attempt to access numberList
throws a runtime exception:
ClassCastException: class [I cannot be cast to class java.lang.Integer
This confirms that the contents of the list are not what we expected - an array of ints ([I
) instead of a list of Integer
objects.
Well, my IDE did flag new ArrayList(Arrays.asList(numbers))
with a warning:
Confusing primitive array passed to varargs method
And:
A primitive array passed to variable-argument method will not be unwrapped and its items will not be seen as items of the variable-length argument in the called method. Instead, the array will be passed as a single item.
The vararg
in this case is the argument passed to Arrays.asList(T... a)
.
It turns out this issue is covered eloquently in Josh Bloch’s Effective Java (Third Edition, in my case). Item 32: “Combine generics and varargs judiciously” states:
when you invoke a varargs method, an array is created to hold the varargs parameters…
He goes on to ask “why is it even legal to do this…?” Because the usefulness outweighs the downside of this inconsistency.
One alternative approach these days is to use a stream to box the array of primitive int
values:
|
|