Java 8与Java 9中的数组转换

11

有人知道为什么这段代码在Java 8上可以运行,但在Java 9上不能吗?

String[] strings = (String[]) Arrays.asList("foo", "bar").toArray();
for (String string : strings) {
    System.out.println(string);
}

我知道我们可以在toArray时指定类型而不是强制转换它。但是我在调试依赖项(hive-metastore-2.1.1 HiveMetaStoreClient line 274)时发现了这个问题。所以我没有自由更改代码,我们正在运行java 9。有什么方法可以解决这个问题吗?这是java 9的问题(因为它似乎是一个破坏性的变化),还是只需在hive repo中报告错误。

1
请参见JDK-6260652 - Johannes Kuhn
3
toArray() 方法不带参数时返回的是 Object[] 类型,因此将其强制转换为 String[] 是不正确的。在 JDK 8 中代码“起作用”实际上是一个 bug。JDK 10 中对规范进行了澄清,请参阅 JDK-8160406。与此同时,获取字符串数组的最佳方法类似于以下示例:String[] strings = Arrays.asList("foo", "bar").toArray(new String[0]) - Stuart Marks
2个回答

13

看起来可能是由于更改导致的(coll) Arrays.asList(x).toArray().getClass() 应该是 Object[].class

似乎他们修复了一个bug,使得toArray返回的类型可能不是Object。

引用发布说明

这可能会导致期望旧行为的代码失败,并出现ClassCastException...如果发生此问题,请重写代码以使用one-arg形式的toArray(T []),并提供所需数组类型的实例。这也将消除需要强制转换的需要。

因此,看起来您需要在Hive repo中提交错误以在更改后更新代码。

看起来他们实际上在未来的提交中添加了一个配置值,如果设置为某个特定值,则可以避免导致问题的代码路径。 https://github.com/apache/hive/commit/07492e0d2f1942c1794a3190610e10207c850cf7#diff-ca39aa4869cc58909a31c761cd7a27ccR257

也许您可以升级到具有此功能并使用此配置以避免问题的版本。只要您不关心需要该代码路径的功能。似乎引起问题的代码是随机选择要使用的URI,而不仅仅是从列表中选择第一个。

6
< p>看起来 Arrays.ArrayList.toArray 的实现已经改变了。旧的实现方式只是克隆后备数组

private final E[] a;

ArrayList(E[] array) {
    a = Objects.requireNonNull(array);
}

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

新的实现强制返回数组为Object[]类型:

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

要明确的是,在Java 8中,强制转换只起作用是因为支持数组最初是由asList可变参数创建的String[]。隐含的所有操作都是new String[] {"foo", "bar"}.clone(),但是该数组通过asList List实现传递。
至于修复损坏的依赖关系,除了使用Java 8运行时环境或重写提交中引入的内容之外,我认为没有其他方法。提交错误报告似乎是正确的做法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接