List <Dog>是List <Animal>的子类吗?为什么Java泛型不是隐式多态的? - java

我对Java泛型如何处理继承/多态感到困惑。

假设以下层次结构-

动物(父母)

狗-猫(儿童)

因此,假设我有一个方法doSomething(List<Animal> animals)。根据继承和多态性的所有规则,我假设List<Dog>List<Animal>,而List<Cat>List<Animal>-因此可以将任何一个传递给此方法。不是这样如果要实现此行为,我必须通过说doSomething(List<? extends Animal> animals)明确告诉该方法接受Animal的任何子类的列表。

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

参考方案

不,List<Dog>不是List<Animal>。考虑使用List<Animal>可以做什么-您可以向其中添加任何动物...包括猫。现在,您可以在逻辑上将猫添加到一窝小狗中吗?绝对不。

// 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?

突然,你有一只非常困惑的猫。

现在,您不能将Cat添加到List<? extends Animal>,因为您不知道它是List<Cat>。您可以检索一个值并知道它将是一个Animal,但不能添加任意动物。对于List<? super Animal>,情况恰恰相反-在这种情况下,您可以安全地向其中添加Animal,但是对于从中检索到的内容一无所知,因为它可能是List<Object>

无法从ArrayList <String>转换为List <Comparable> - java

当我写下面的代码时,编译器说 无法从ArrayList<String>转换为List<Comparable>private List<Comparable> get(){ return new ArrayList<String>(); } 但是当我用通配符编写返回类型时,代码会编译。private List&l…

合并List <T>和List <Optional <T >> - java

鉴于: List<Integer> integers = new ArrayList<>(Arrays.asList( 10, 12 )); List<Optional<Integer>> optionalIntegers = Arrays.asList( Optional.of(5), Optional.em…

实例化类型<?>的泛型类 - java

我正在为SCJP / OCPJP学习,并且遇到了一个对我来说很奇怪的示例问题。该示例代码实例化了两个通用集合:List<?> list = new ArrayList<?>(); List<? extends Object> list2 = new ArrayList<? extends Object>(); …

在HashMap <String,String>上循环时出现问题 - java

我有一个基本的HashMap。我正在尝试遍历它,并从Map中获取键和值。这是我所拥有的:Map<String, String> myMap = versionExtractor.getVersionInfo(); for(String key : myMap.keySet()) System.out.println(key); System.ou…

OpenShift构建错误:无法在多模块Maven Spring启动项目的父模块中导入子模块类 - java

我有一个使用spring的多模块Maven项目。通用模块类用作业务模块项目中的直接导入。我可以在本地PC上编译并成功运行它们。当我在OpenShift中部署相同的模块时,出现错误,无法在业务模块中导入通用模块类。项目结构可以总结如下:项目根 通用模块 src pom.xml 业务模块 src pom.xml pom.xml父POM:<?xml vers…