数组转换 Java 8 与 Java 9

array cast Java 8 vs Java 9

有谁知道为什么这段代码适用于 java 8 但不适用于 java 9

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

我知道我们可以在执行 toArray 时指定类型而不是转换它。但是我在调​​试我们的 dependency 之一时发现了这个问题(hive-metastore-2.1.1 HiveMetaStoreClient 第 274 行)。所以我没有更改代码的自由,我们 运行 java 9. 有没有办法解决这个问题?这是 java 9 的问题(因为它看起来像是一个重大更改)还是只是在配置单元 repo 中提交错误。

Arrays.ArrayList.toArray 的实施似乎已更改。 The old implementation was to just clone the backing array:

private final E[] a;

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

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

The new implementation forces the returned array to be an 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 运行 时间环境或重写该提交中引入的内容之外没有其他方法。提交错误报告似乎是正确的做法。

似乎是因为变化(coll) Arrays.asList(x).toArray().getClass() should be Object[].class

看起来他们修复了 toArray 可以 return 除 Object 之外的类型的错误。

引用发行说明

This may cause code that was expecting the old behavior to fail with a ClassCastException...If this problem occurs, rewrite the code to use the one-arg form toArray(T[]), and provide an instance of the desired array type. This will also eliminate the need for a cast.

因此,您似乎需要在 Hive 存储库中提交错误,以更新代码以在此次更改后正常工作。

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

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