[英]Java generics, using <? extends Superclass>, clarification needed
[英]using extends with Java Generics
可以说我有以下代码:
public class Shelter<A extends Animal, B extends Animal>
{
List<A> topFloor = new Vector<A>();
List<B> bottomFloor = new Vector<B>();
public A getFirstTopFloorAnimal(){return topFloor.get(0);}
public B getFirstBottomFloorAnimal(){return bottomFloor.get(0);}
//These 3 methods compile but when I try to use it, they all only return objects
public List<Animal> getAnimals()
{
List<Animal> a = new Vector<Animal>(topFloor);
a.addAll(bottomFloor);
return a;
}
public List<A> getTopFloor(){return topFloor;}
public List<B> getBottomFloor(){return bottomFloor;}
}
然后,我尝试执行以下操作:
for(Animal a : shelter.getTopFloor()){
a.growl();
}
但是我遇到了一个编译器错误,我得到的错误是A是一个对象,而不是动物。 如果我尝试使用其他方法,也会发生相同的情况。 任何想法为什么会这样? 这与泛型教程中的List<String>
不是List<Object>
想法有关吗?
谢谢
泛型只是为了提高类型安全性的编译时概念。
您不能在运行时使用它们来过滤添加到集合中的值。 您必须手动进行过滤( instanceOf
,使用instanceOf
)
例如,这将起作用,并允许您添加一个Date
:
List<String> list = new ArrayList<String>();
((List) list).add(new Date());
因此,解决您的问题(我们尚未发现)的解决方案是在添加元素时不使用原始类型。
我最好的猜测是,您已经声明使用以下原始类型来shelter
:
Shelter shelter = new Shelter();
您确实应该执行以下操作:
Shelter<Cat,Dog> shelter = new Shelter<Cat,Dog>();
然后,您实际上将使用泛型功能。
有效的Java 2nd Edition : 项目23:不要在新代码中使用原始类型 。
如果使用原始类型,则将失去泛型的所有安全性和表达优势。
原始类型的使用仅允许作为遗留代码兼容性的让步。 强烈建议不要在将通用性引入Java编程语言之后在编写的代码中使用原始类型。 未来版本的Java编程语言可能会禁止使用原始类型。
List<String>
不是List<Object>
是的,Java泛型既不是协变也不是协变 。 如果您试图将一种泛型类型转换为另一种泛型类型,那只是一个问题,这似乎并不是您要尝试做的。
另外,与您的主题标题所说的不同,我认为这与extends
以绑定泛型中的类型参数没有任何关系。
我认为您问题的核心在这里:
for(Animal a : shelter.getTopFloor()){
a.growl();
}
如何定义shelter
所?
这是因为当您将项目放入Vector
,它们作为对象进入,而不是Animal
实例。
public List<Animal> getAnimals()
{
Vector a = new Vector(topFloor); // <-- Not generic!
a.addAll(bottomFloor);
return a; // <-- Returning non-generic Vector.
}
试试这个:
Vector<Animal> a = ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.