java - 为什么这个带有泛型的代码会在 Java 11 中引发 ClassCastException?

标签 java generics

下面的代码在 Java 8 中成功,但在 Java 11 中抛出 ClassCastException。为什么行为会发生变化?

我在 OpenJDK 的 Java 9、Java 10 或 Java 11 功能集中找不到任何相关更改。

public class GenericsExample {

    public static void main(String[] args) {
        Set<Car> set = new HashSet<>();
        set.add(getAnimal());
    }

    static <T extends Animal> T getAnimal() {
        return (T) new Animal() {};
    }

    interface Animal {}

    class Car {}
}

最佳答案

确实是 bug在 Java 8 中,已在 Java 9 中修复 - bugfix .
在某些情况下,javac CHECKCAST指令被跳过。

如果您好奇,请考虑以下两行代码:

Set<Car> set = new HashSet<>(); // line 11
set.add(getAnimal());           // line 12

Java 8 字节码将如下所示:
 LINENUMBER 11 L1
 ALOAD 1
 ALOAD 0
 INVOKEVIRTUAL UserManagerTest.getAnimal ()LUserManagerTest$Animal;
 INVOKEINTERFACE java/util/Set.add (Ljava/lang/Object;)Z (itf)
 POP

但是 Java 9 看起来像这样:
LINENUMBER 11 L1
ALOAD 1
ALOAD 0
INVOKEVIRTUAL UserManagerTest.getAnimal ()LUserManagerTest$Animal;
CHECKCAST UserManagerTest$Car
INVOKEINTERFACE java/util/Set.add (Ljava/lang/Object;)Z (itf)
POP

唯一的区别是 CHECKCAST指令,(根据 JavaDoc )声明命名的类、数组或接口(interface)类型已解析。如果 object 可以转换为已解析的类、数组或接口(interface)类型,则操作数堆栈不变;否则,checkcast 指令会抛出 ClassCastException。

关于java - 为什么这个带有泛型的代码会在 Java 11 中引发 ClassCastException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54334575/

相关文章:

c# - IList实现测试

java - 如何按降序对 ArrayList 进行排序?

java - 如何在java中实现将泛型类型数组转换为泛型类型二维数组的函数?

java - 如何从jmeter调用java类?

java - Tomcat 7 上的 OrientDB JDBC 连接器池

c# - IsOrderedBy 扩展方法

c# - 在简单注入(inject)器中注册具有构造函数参数的泛型类型

java通用模板错误

java - 如何使用 CMIS 删除文档

java - Gui 用于调试比较并行文件中的大型 Java 对象集合。