Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Arrays.asList(...).toArray().getClass() give different results in JDK 8 and 9? [duplicate]

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()
like image 733
Felix Avatar asked Dec 09 '18 20:12

Felix


People also ask

Does Arrays asList make a copy?

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.

What does Arrays asList () do?

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.

What does array asList return?

asList returns a fixed-size list that is​ backed by the specified array; the returned list is serializable and allows random access.

Can you modify the collection return by Arrays asList ()?

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.


2 Answers

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[]), its toArray() will return an array of the same type (because it use clone()) instead of an Object[].

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]);
like image 100
Jorn Vernee Avatar answered Oct 19 '22 03:10

Jorn Vernee


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.

like image 12
Thomas Kläger Avatar answered Oct 19 '22 03:10

Thomas Kläger