Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/kubernetes/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么这段带有泛型的代码在Java11中抛出ClassCastException?_Java_Generics - Fatal编程技术网

为什么这段带有泛型的代码在Java11中抛出ClassCastException?

为什么这段带有泛型的代码在Java11中抛出ClassCastException?,java,generics,Java,Generics,下面的代码在Java8中成功,但在Java11中抛出ClassCastException。为什么行为会改变 我在OpenJDK的Java9、Java10或Java11特性集中找不到任何相关的更改 public class GenericsExample { public static void main(String[] args) { Set<Car> set = new HashSet<>(); set.add(getAnim

下面的代码在Java8中成功,但在Java11中抛出ClassCastException。为什么行为会改变

我在OpenJDK的Java9、Java10或Java11特性集中找不到任何相关的更改

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 {}
}
公共类泛型示例{
公共静态void main(字符串[]args){
Set=newhashset();
set.add(getAnimal());
}
静态T getAnimal(){
返回(T)新动物(){};
}
界面动物{}
类车{}
}
事实上,它在Java8中是一个错误,在Java9中是固定的。 在某些场景中,跳过了javac
CHECKCAST
指令

如果你很好奇,就考虑这2行代码:

Set<Car> set = new HashSet<>(); // line 11
set.add(getAnimal());           // line 12
但Java 9将如下所示:

 LINENUMBER 11 L1
 ALOAD 1
 ALOAD 0
 INVOKEVIRTUAL UserManagerTest.getAnimal ()LUserManagerTest$Animal;
 INVOKEINTERFACE java/util/Set.add (Ljava/lang/Object;)Z (itf)
 POP
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
指令,它(根据)声明已解析命名的类、数组或接口类型。如果对象可以转换为解析的类、数组或接口类型,则操作数堆栈不变;否则,checkcast指令将抛出ClassCastException。

您正试图将Animal添加到汽车集合中。。。这是怎么回事?O.oNote指出,这种仅返回类型的通用参数需要非常小心地使用,另请参见。当涉及交叉类型和有界泛型参数时,有几个与类型推断相关的错误。据我所知,强制转换的
getAnimal()
从未转换为运行时检查-擦除后,如果我没有弄错的话,这只是
static Animal getAnimal()
,编译器接受它是因为
Animal
是一个接口,可能有一个
Car
也是
Animal
,因此它推断
T
Car
Animal
的连接类型,它编译得很好-但它应该生成一个运行时检查来验证这一点。我觉得有些版本无法在调用站点插入此运行时检查。如果
Animal
是一个类,则在我测试的所有版本中编译都会失败。另外请注意,如果您确实知道自己在做什么,这是一个很好的参数,可以仅禁止或忽略“unchecked cast”警告-
return(T)new Animal(){
会导致这样的警告,因为编译器无法保证您的
Animal
的匿名子类型确实是
T