登陆

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

admin 2022-11-25 4人围观 ,发现0个评论

为什么以下条件返回trueJDK 8,而它返回falseJDK 9?

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

Jorn Vernee.. 51

List返回的类型asListArrays$ArrayList.在toArray对类在JDK 8的方法是:

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

但在JDK 9+中它是:

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

在这两种情况下String[]都传递给a 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文档声称

collection.toArray() 

是"功能相同"

collection.toArray(new Object[0]); 

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

如果后来尝试在该数组中存储非字符串(或其他),ArrayStoreException则抛出一个.

所以这个改变是为了修复以前的行为.


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

如果出现此问题,请重写代码以使用one-arg表单toArray(T[]),并提供所需数组类型的实例.这也将消除演员阵容的需要.

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

有趣的是[`ArrayList(Collection)`构造函数](http://hg.openjdk.java.net/jdk6/jdk6/jdk/file/8deef18bb749/src/share/classes/java/util/ArrayList.java #l144)包含对这种不良行为的保护,参考这个错误报告(它来自2005年)很长一段时间,而没有人首先想到修复不端行为,显然...... (3认同)


Thomas Kläge.. 12

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

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



1> Jorn Vernee..:

List返回的类型asListArrays$ArrayList.在toArray对类在JDK 8的方法是:

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

但在JDK 9+中它是:

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

在这两种情况下String[]都传递给a 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文档声称

collection.toArray() 

是"功能相同"

collection.toArray(new Object[0]); 

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

如果后来尝试在该数组中存储非字符串(或其他),ArrayStoreException则抛出一个.

所以这个改变是为了修复以前的行为.


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

如果出现此问题,请重写代码以使用one-arg表单toArray(T[]),并提供所需数组类型的实例.这也将消除演员阵容的需要.

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


有趣的是[`ArrayList(Collection)`构造函数](http://hg.openjdk.java.net/jdk6/jdk6/jdk/file/8deef18bb749/src/share/classes/java/util/ArrayList.java #l144)包含对这种不良行为的保护,参考这个错误报告(它来自2005年)很长一段时间,而没有人首先想到修复不端行为,显然......

2> Thomas Kläge..:

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

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


那是不对的.该方法总是返回`Object []`(只看它的返回类型声明).它从未违反其声明的类型.相反,它违反了其记录的运行时行为.区别在于细微差别,但却很重要.
关于此更改的JDK 9发行说明如下:https://www.oracle.com/technetwork/java/javase/9​​-notes-3745703.html#JDK-6260652
请发表您的评论
请关注微信公众号
微信二维码
不容错过
Powered By Z-BlogPHP