Jit*_*dra 4 java generics collections language-lawyer
根据 Maurice Naftalin 的 Java Generic 和 Collections,在以下选项中 -
第一个和第二个是允许的,但第三个不是,它在 java 8(版本“1.8.0_321”)中工作正常。选项1和2编译,选项3给出编译错误。但第三个选项适用于 java 17(版本“17.0.1”2021-10-19 LTS)。你能帮我理解为什么它在 java 17 中工作吗?我正在尝试的示例代码 -
var a = List.of(2,3,4,5,23);
var b = a instanceof List<? extends Object>;
return b;
Run Code Online (Sandbox Code Playgroud)
在 Java\xc2\xa016 之前, 的唯一目的instanceof
是检查引用的对象是否可分配给指定类型,并且由于类型擦除阻止检查对象是否真正可分配给参数化类型,因此允许假装这样的测试是可能的。
唯一可以测试的是该对象是否是 的实例List
,因此,只允许写入\xe2\x80\xa6 instanceof List
或\xe2\x80\xa6 instanceof List<?>
,因为两者都没有假装测试 list\xe2\x80\x99s 元素类型。
从 Java\xc2\xa016(从 14 开始提供预览版)开始,instanceof
允许声明指定类型的新变量。
例如:
\npublic void someMethod(Iterable<String> i) {\n if(i instanceof List<String> l) {\n if(l.isEmpty()) return;\n // optimized List processing\n } else {\n // generic iterable processing\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n这相当于
\npublic void someMethod(Iterable<String> i) {\n if(i instanceof List<String>) {\n List<String> l = (List<String>)i;\n if(l.isEmpty()) return;\n // optimized List processing\n } else {\n // generic iterable processing\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n对于新变量的声明,限制为原始类型或通配符类型是不切实际的。因此,现在允许指定与隐含变量声明和赋值相关的实际类型参数。由于仍然无法检查元素类型\xe2\x80\x99,因此仅允许指定编译时源类型可以在不进行未经检查的强制转换的情况下强制转换为的类型。
\n因此,以下内容无效
\nIterable<?> i = null;\nboolean b = i instanceof List<String>;\n
Run Code Online (Sandbox Code Playgroud)\n因为您可以\xe2\x80\x99t 安全地从 转换Iterable<?>
为List<String>
.
在您的示例中,var a = List.of(2,3,4,5,23);
声明a
为List<Integer>
,因此,a instanceof List<? extends Object>
是有效的,因为List<Integer>
可分配给List<? extends Object>
(即使没有强制转换)。
当然,只有在像第一个示例中那样声明变量时,指定未检查的元素类型才有用。但 Java 语言遵循的原则是,不会仅仅因为某些构造的用处不如其他构造而添加额外的规则。instanceof
因此,无论是否声明变量,您现在始终可以指定实际类型参数以遵循相同的规则。
此功能称为模式匹配,因为它被认为是 Java 所追求的更广泛概念的特例。在 JDK\xc2\xa017 中,\xe2\x80\x99 有类似的功能可供switch
预览。
另请参见\xc2\xa714.30。Java 语言规范中的模式。
\n