我的印象是,在Java中,由于类型擦除,instanceof操作符不能用于泛型.但是,下面代码片段中的第一个条件语句编译和运行时没有任何错误.有人能解释为什么第一个条件不会导致编译时错误吗?我正在使用IntelliJ IDEA与Oracle JDK 17.

public class InstanceofTest {
    public static class Tea {}
    public static class Herb {}

    // Why is this working?
    public static void main(String[] args) {
        List<Tea> teas = new ArrayList<>();

        if (teas instanceof List<Tea>) {
            System.out.println("TRUE");
        } else {
            System.out.println("FALSE");
        }

        // Compile error
        // if (teas instanceof List<Herb>) {
        //     System.out.println("TRUE");
        // } else {
        //     System.out.println("FALSE");
        // }
    }
}

推荐答案

在Java中,像List<Tea>这样的泛型在代码运行时被缩减为List,这就是为什么你通常不能将instanceof与泛型类型一起使用.instanceof List<Tea>工作的原因是,在编译时,Java编译器只判断List<Tea>List部分.它不关心<Tea>部分,因为类型擦除,但它不会抛出错误,因为它不是wrong以这样的方式写,而且语法本身也没有错误.编译器知道你正在处理上下文中的List<Tea>,所以它不会反对.

另一方面,当你try instanceof List<Herb>时,编译器会介入,因为它知道你的列表不可能是List<Herb>,因为你的toldList<Tea>.这在编译时发生,基于您提供的信息,而不管列表在运行时的实际内容是什么.

TL;DR:
Java compiler makes decisions based on the information available at compile time, not on the actual contents of the list during runtime, due to type erasure.

Java相关问答推荐

Jooq隐式地将bigint转换为数字,并且索引不起作用

Java事件系统通用转换为有界通配符

Listview—在Android Java中正确链接项目时出错

JUnit—如何模拟局部变量对象方法调用

Java inline Double条件和值解装箱崩溃

通过合并Akka Streams中的多个慢源保持订购

DTO到实体,反之亦然,控制器和服务之间的哪一层应该处理转换?

连接Quarkus中的两个异步操作

AssertJ Java:多条件断言

如何让DTO接受空字符串字段,但如果它们不为空,则应用JPA验证?

GSON期间的Java类型擦除

通过移动一个类解决了潜在的StubbingProblem.它怎麽工作?

如何使用带有谓词参数的方法,而不使用lambda表达式

JOOQ中的子查询使用的是默认方言,而不是配置的方言

与不同顺序的组进行匹配,不重复组但分开

Java泛型类方法的静态返回类型是否被类型擦除?

垃圾收集时间长,会丢弃网络连接,但不会在Kubernetes中反弹Pod

X=x*0.90;产生有损转换误差.X*=0.90;不是.为什么?

为什么没有加载java.se模块?

spring 更新多项管理关系