为什么Arrays.asList(...)。toArray()。getClass()在JDK 8和9中给出不同的结果?

时间:2018-12-09 20:51:42

标签: java java-8 java-9

为什么以下条件在JDK 8中返回true而在JDK 9中返回false

String[].class == Arrays.asList("a", "b").toArray().getClass()

2 个答案:

答案 0 :(得分:51)

List返回的asList类型为Arrays$ArrayList。 JDK 8中该类上的toArray方法是:

@Override
public Object[] toArray() {
    return a.clone();
}

但是在JDK 9+中,它是:

@Override
public Object[] toArray() {
    return Arrays.copyOf(a, a.length, Object[].class);
}

在两种情况下,都将String[]传递给asList,但是在JDK 8情况下,它将被克隆并保留其数组类型(String[]),而在JDK 9+中会被克隆。是使用Arrays.copyOf复制的,其显式新数组类型为Object[]

这种差异意味着在JDK 8中Arrays.asList("a", "b").toArray().getClass()返回String[],在JDK 9+中返回Object[],因此在JDK 9+中您的表达式将得出false

做出此更改的原因来自JDK-6260652,其动机是:

  

馆藏文档声称

collection.toArray()
     

与“在功能上相同”

collection.toArray(new Object[0]);
     

但是,Arrays.asList的实现并不遵循以下规则:如果创建了带有子类型(例如String[])的数组,则其toArray()将返回相同类型的数组(因为它使用clone())而不是Object[]

     

如果以后尝试在该数组中存储非字符串(或其他任何内容),则会抛出ArrayStoreException

因此进行了此更改以修复以前的行为。


如果这对您来说是个问题,相关的release note可以提供解决方法:

  

如果发生此问题,请重写代码以使用one-arg形式toArray(T[]),并提供所需数组类型的实例。这也将消除强制转换的需要。

String[] array = list.toArray(new String[0]);

答案 1 :(得分:12)

我想说这是JDK 8中的一个错误,在此之前已被修复。

List<T>.toArray()始终被声明为返回Object[](请参阅JavaDoc)-实际上在特殊情况下它实际上返回了String[]是一个错误。