繁体   English   中英

Java 具有通用版本 8 和 17 的实例类型

[英]Java instance type with generic version 8 vs 17

根据 Maurice Naftalin 的 Java Generic 和 Collections,在以下选项中 -

  1. 对象实例列表
  2. obj 实例列表<?>
  3. obj 实例列表<? 扩展对象>

第一和第二是允许的,但第三不是在 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;

在 Java 16 之前, instanceof的唯一目的是检查引用的 object 是否可分配给指定的类型,并且由于类型擦除阻止检查 object 是否真的可分配给参数化类型,因此允许表达式伪装是没有意义的这样的测试是可能的。

唯一可以测试的是 object 是否是List的实例,因此,它只允许写… instanceof List… instanceof List<?> ,因为两者都没有假装测试列表的元素类型。

从 Java 16(自 14 开始提供预览版)开始, instanceof允许声明指定类型的新变量。

例如:

public void someMethod(Iterable<String> i) {
    if(i instanceof List<String> l) {
        if(l.isEmpty()) return;
        // optimized List processing
    } else {
        // generic iterable processing
    }
}

这相当于

public void someMethod(Iterable<String> i) {
    if(i instanceof List<String>) {
        List<String> l = (List<String>)i;
        if(l.isEmpty()) return;
        // optimized List processing
    } else {
        // generic iterable processing
    }
}

对于新变量的声明,仅限于原始类型或通配符类型是不切实际的。 因此,现在允许指定与隐含变量声明和赋值相关的实际类型 arguments。 由于仍然无法检查元素类型,因此您只能指定编译时源类型可以在没有未经检查的强制转换的情况下强制转换为的类型。

因此,以下内容无效

Iterable<?> i = null;
boolean b = i instanceof List<String>;

因为您不能安全地从Iterable<?>转换为List<String>

在您的示例中, var a = List.of(2,3,4,5,23); a声明为List<Integer> ,因此, a instanceof List<? extends Object> a instanceof List<? extends Object>是有效的,因为List<Integer>可以分配给List<? extends Object> List<? extends Object> (即使没有演员表)。

当然,指定未检查的元素类型仅在您像第一个示例中那样声明变量时才有用。 但是 Java 语言遵循不添加额外规则的原则,因为某些构造比其他构造不太有用。 因此,无论您是否声明变量,您现在始终可以按照相同的规则将实际类型 arguments 指定给instanceof

此功能称为模式匹配,因为它被认为是 Java 所追求的更广泛概念的特例。 在 JDK 17 中,有一个类似的switch功能可用作预览版。

另见§14.30。 Java语言规范中的模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM