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

2022-09-01 01:02:53

为什么以下条件随 JDK 8 一起返回,而与 JDK 9 一起返回?truefalse

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

答案 1

返回的类型是 Arrays$ArrayList。该类上的 JDK 8 中的方法是:ListasListtoArray

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

但在JDK 9+中,它是:

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

在这两种情况下,a 都被传递给 ,但在 JDK 8 情况下,它被克隆,它保留其数组类型 (),而在 JDK 9+ 中,它被复制为与显式的新数组类型 。String[]asListString[]Arrays.copyOfObject[]

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

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

“集合”文档声称

collection.toArray()

在功能上相同”

collection.toArray(new Object[0]);

但是,的实现并不遵循以下条件:如果使用子类型的数组(例如)创建,它将返回相同类型的数组(因为它使用),而不是 .Arrays.asListString[]toArray()clone()Object[]

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

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


如果这对您来说是一个问题,相关的发行说明会提供以下解决方法:

如果出现此问题,请重写代码以使用 one-arg 形式 ,并提供所需数组类型的实例。这也将消除对铸件的需求。toArray(T[])

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

答案 2

我会说这是JDK 8中的一个错误,之前已经修复了。

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


推荐