Why does the following condition return true
with JDK 8, whereas it returns false
with JDK 9?
String[].class == Arrays.asList("a", "b").toArray().getClass()
asList method. Using this method, we can convert from an array to a fixed-size List object. This List is just a wrapper that makes the array available as a list. No data is copied or created.
The asList() method of java. util. Arrays class is used to return a fixed-size list backed by the specified array. This method acts as a bridge between array-based and collection-based APIs, in combination with Collection.
asList returns a fixed-size list that is backed by the specified array; the returned list is serializable and allows random access.
Using Arrays. Arrays. asList() method returns a fixed-size list backed by the specified array. Since an array cannot be structurally modified, it is impossible to add elements to the list or remove elements from it.
The List
type returned by asList
is Arrays$ArrayList
. The toArray
method in JDK 8 on that class is:
@Override
public Object[] toArray() {
return a.clone();
}
But in JDK 9+ it is:
@Override
public Object[] toArray() {
return Arrays.copyOf(a, a.length, Object[].class);
}
In both cases a String[]
is passed to asList
, but in the JDK 8 case it is cloned, which retains its array type (String[]
), and in JDK 9+ it is copied using Arrays.copyOf
with the explicit new array type of Object[]
.
This difference means that in JDK 8 Arrays.asList("a", "b").toArray().getClass()
returns String[]
and in JDK 9+ it returns Object[]
, so in JDK 9+ your expression will evaluate to false
.
The reason for this change comes from JDK-6260652 with the motivation:
The Collection documentation claims that
collection.toArray()
is "identical in function" to
collection.toArray(new Object[0]);
However, the implementation of
Arrays.asList
does not follow this: If created with an array of a subtype (e.g.String[]
), itstoArray()
will return an array of the same type (because it useclone()
) instead of anObject[]
.If one later tries to store non-Strings (or whatever) in that array, an
ArrayStoreException
is thrown.
So this change was made to fix the previous behaviour.
If this is a problem for you, the related release note offers this as a work-around:
If this problem occurs, rewrite the code to use the one-arg form
toArray(T[])
, and provide an instance of the desired array type. This will also eliminate the need for a cast.String[] array = list.toArray(new String[0]);
I would say that this was a bug in JDK 8 and before that has been fixed.
List<T>.toArray()
was always declared as returning Object[]
(see JavaDoc) - that it did in effect return String[]
in a special case was a mistake.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With