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

虾米哥 阅读:13 2024-06-20 12:54:19 评论:0

下面的代码在 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
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号