java - 如果没有中间变量,泛型代码无法编译

标签 java generics

令我惊讶的是,编译器允许下面的 main 中的前两行代码。当我说 getIt() 将返回 Dog 时,它似乎信任我,即使签名也允许返回 Cat

public class GenericsAreWeird {
    public static void main(String... args){
        // This is fine
        Dog d = getIt();
        d.woof();

        // This fails to compile
        // getIt().woof();

        // This compiles but gives a runtime ClassCastException
        Cat c = getIt();
        c.meow();
    }

    private static <T extends Animal> T getIt(){
        return (T) new Dog();
    }

    public static class Animal {}

    public static class Cat extends Animal{
        public void meow(){}
    }

    public static class Dog extends Animal{
        public void woof(){}
    }
}

我通常相信 Java 泛型会通过给出编译器错误来保护我免受 ClassCastExceptions 的影响,而不是在运行时告诉我某些东西不起作用,因此允许这样做似乎是错误的。

这似乎也违反直觉:

Dog d = getIt();
d.woof();

并不完全等同于:

getIt().woof();

编译器需要中间变量作为“提示”。

泛型一直都是这样工作的吗?有人可以向我指出(或提供)编译器无法识别此类与类相关的错误的任何其他场景的合理解释吗?

最佳答案

return (T) new Dog(); 大多数情况下告诉编译器
“闭嘴你的类型检查,我比你更清楚 Dog 总是可以分配给 T
编译器回复
“好吧,那就继续吧,那么你最好注意不要调用这个方法并期望它返回任何其他内容/aCat

然后你确实调用它,期望它返回一个Cat并得到一个应得的ClassCastException。您得到运行时异常是因为您告诉编译器您更了解它(但您并不了解)。

关于java - 如果没有中间变量,泛型代码无法编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59983030/

相关文章:

java - 检索文件夹和子文件夹以使用尾递归在 Java 中读取文件

java - 我可以在自定义 Jackson 序列化程序中访问其他模型属性吗?

java - Camel::Generic List<Enum> 转换器

c# - 泛型的默认值

typescript 中的 Angular : how to pass generic Type to function

java - 将子类型中类型参数的注释链接到父类(super class)型中声明类型参数

java - java.lang.NumberFormatException 问题

java - mysql访问被jdbc拒绝

java - Maven 通过另一个 pom 管理依赖关系

c++ - C++中不相关T的容器