从 JDK8 迁移到 JDK11 导致 java.lang.UnsupportedOperationException

Mut*_*ani 1 java collections hashset java-8 java-11

我正在将我的一个项目从 JDK8 迁移到 JDK11,但是其中一个单元测试失败了,尽管我想出了如何在 JDK11 中解决此问题的解决方案,但我不知道其背后的原因。如果有人向我解释这一变化,我真的很感激。这是适用于 JDK8 但不适用于 JDK11 的 HashSet:

Set<String> func(Properties p, String s) {
    Set<String> set = p.stringPropertyNames();
    set.removeIf(s -> !s.startsWith(s));
    return set;
}
Run Code Online (Sandbox Code Playgroud)

我不得不像这样更改 HashSet 初始化以使我的测试运行并通过 JDK11:

Set<String> set = new HashSet<>(p.stringPropertyNames());
Run Code Online (Sandbox Code Playgroud)

我不明白为什么我必须在 JDK11 中像这样更改初始化,此更改是否打算在 JDK11 中使用?

错误堆栈跟踪:

null
java.lang.UnsupportedOperationException
at java.base/java.util.Collections$UnmodifiableCollection.removeIf(Collections.java:1089)
Run Code Online (Sandbox Code Playgroud)

Ste*_*n C 11

既然您已经解释了类型properties是什么java.util.Properties,答案就很清楚了。在 Java 8 中,Properties.stringPropertyNames()返回一个未指定可修改性的集合:

"返回此属性列表中的一组键,其中键及其对应的值是字符串,如果尚未从主属性列表中找到同名的键,则在默认属性列表中包括不同的键。其键或值不是字符串类型被省略。”

“返回的集合不受属性对象的支持。对此属性的更改不会反映在集合中,反之亦然。” .

在 Java 11 中,它被指定为不可修改。

"从该属性列表中返回一组不可修改的键,其中键及其对应的值是字符串,如果尚未从主属性列表中找到同名的键,则在默认属性列表中包括不同的键。其键的属性或值不是字符串类型被省略。”

“返回的集合不受此 Properties 对象的支持。对此 Properties 对象的更改不会反映在返回的集合中。”

更改发生在 Java 9 中。这与错误 8059361相关。

(这是一个不兼容的更改,如果客户依赖于能够修改返回的集合,它可能会破坏客户的代码。但是,该代码依赖于未指定的行为,因此您可以争辩说它已经被破坏了。)