首页 文章

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

提问于
浏览
37

这个问题在这里已有答案:

为什么以下条件返回 true 与JDK 8,而它返回 false 与JDK 9?

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

2 回答

  • 45

    asList 返回的 List 类型为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文档声称collection.toArray()
    与函数“相同”至collection.toArray(new Object [0]);
    但是,Arrays.asList的实现不遵循:如果使用子类型数组(例如String [])创建,其toArray()将返回相同类型的数组(因为它使用clone())而不是一个东西[] . 如果后来尝试在该数组中存储非字符串(或其他),则抛出ArrayStoreException .

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


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

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

  • 10

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

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

相关问题