Generics subclass behavior in java
嗨,我有下面代码中的查询。
当我声明动物列表时,它允许我将cat()和dog()放在其中,因为它们都是动物,满足是关系船。
1 2 3 4 5 6
| Class Cat extends Animal{}
Class Dog extends Animal{}
List<Animal> list = new ArrayList<Animal>();
list.add(new Dog());//Code works fine
list.add(new Cat());//Code works fine |
现在我的问题是,如果? extends意味着接受动物的任何子类,那么为什么不编译下面的代码呢?
1 2 3
| List<? extends Animal> list = new ArrayList<Animal>();
list.add(new Dog());//Compilation fails
list.add(new Cat());//Compilation fails |
同样的问题,为什么这里不接受狗?
1 2
| List<? extends Animal> dogs1 = new ArrayList<Dog>();
dogs1.add(new Dog());//Compilation fails |
有人能解释这种行为吗?
- 这绝对是一个副本,有人会标记它。基本上,你的列表可以是动物的任何子类。如果是一个列表,你就不能添加猫,反之亦然。因为Java不能告诉它它是什么,它不允许你添加任何东西。
- @卡亚曼那是个奇怪的"复制品"
- mods请检查有效副本…:(否则不要将其标记为副本
类型为List extends Animal>的变量可以指定为List、List或List。其中一些列表不允许添加Dog,而另一些则不允许添加Cat。
编译器基于list变量的编译时类型,而不是基于运行时分配给它的实际对象,来验证list.add语句的正确性。因此,不接受list.add(new Dog());和list.add(new Cat());。
如果要同时添加Dog和Cat,请使用List类型的变量。
如果只想添加Dogs,请使用List类型的变量。
- @eran-list类型的变量也会做同样的事情,那么为什么list工作正常。
- 因为类型在编译时是已知的,所以编译器可以进行验证
- @showstopper类型为List的变量不能被指定为List或List。因此,您可以安全地添加Dog和Cat。
- @ Eran?扩展动物>列表动物=新的ARARELIST <动物>();列表< CAT> ListCAT= ListStand;这在Java中也是无效的。
- @ERAN-您不能指定list<?类型的变量。将animal>扩展到list、list或list。我刚检查过。请你再检查一下好吗
- @我从没说过你能做到。我说你可以把一个List to a list变量和一个List变量分配给一个List变量。
- @Showstopper You can not assign A variable of type List extends Animal> to a List, a List or a List。我说的是相反的——你可以把一个List赋给一个List extends Animal>变量,而不是另一种方式。
- 明白了,谢谢…:)
- 完全正确…很好的演示