我对Java泛型如何处理继承/多态性有点困惑.

假设以下层次 struct -

Animal(家长)

Dog-Cat( children )

假设我有一个方法doSomething(List<Animal> animals).根据继承和多态性的所有规则,我会假设a List<Dog> is a List<Animal>和a List<Cat> is a List<Animal>,所以任何一个都可以传递给这个方法.不是这样.如果我想实现这种行为,我必须明确地告诉这个方法接受动物任何子类的列表,比如说doSomething(List<? extends Animal> animals).

我知道这是Java的行为.我的问题是why?为什么多态性通常是隐式的,但当涉及泛型时,它必须被指定?

推荐答案

不,List<Dog>notList<Animal>.想一想你能用List<Animal>做什么--你可以在上面加any只动物……包括一只cat .现在,你能合乎逻辑地给一窝小狗加一只cat 吗?绝对不行.

// Illegal code - because otherwise life would be Bad
List<Dog> dogs = new ArrayList<Dog>(); // ArrayList implements List
List<Animal> animals = dogs; // Awooga awooga
animals.add(new Cat());
Dog dog = dogs.get(0); // This should be safe, right?

突然之间,你就有了一只very只困惑的cat .

现在,你can'tList<? extends Animal>的基础上加Cat,因为你不知道它是List<Cat>.您可以检索一个值并知道它将是Animal,但不能添加任意动物.List<? super Animal>的情况正好相反-在这种情况下,您可以安全地向其添加Animal,但您不知道可能从中检索到什么,因为它可能是List<Object>.

Java相关问答推荐

Android视图覆盖不阻止点击它后面的控件

scanner 如何在执行hasNextLine一次后重新读取整个文件?

方法没有用正确的值填充数组—而是将数组保留为null,'

使用标记时,场景大纲不在多个线程上运行

现场观看Android Studio中的变化

如何使用AWS CLI从S3存储桶中的所有对象中删除用户定义的元数据?

扩展到弹出窗口宽度的JavaFX文本字段

在bash中将数组作为Java程序的参数传递

使用REST客户端和对象映射器从字符串反序列化Json

如何正确创建序列图?

如何在JavaFX中处理多个按钮

Kotlin Val是否提供了与Java最终版相同的可见性保证?

如何用内置Java从JavaFX应用程序中生成.exe文件?

如何在ImageIO或十二只猴子中旋转TIFF CMYK图像?

在java中使用不同的application.properties-jar而不使用Spring

为什么我不能建立输入/输出流?Java ServerSocket

如何调整JButton的大小以适应图标?

JavaFX,GridPane:在GridPane的列中生成元素将保持所有列的宽度

在Spring Boot中使用咖啡因进行缓存

Spring Boot Security-每个端点都被403禁止,Spring记录一个BasicErrorController#错误(HttpServlet请求)