为什么以下条件在JDK 8中返回true
而在JDK 9中返回false
?
String[].class == Arrays.asList("a", "b").toArray().getClass()
答案 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[]
是一个错误。