我有以下类结构:
public interface RangeData {
public int getMaxVal();
public int getMinVal();
}
public class IncomeRange implements RangeData {
....
}
//In a utilities class
public RangeData findRangeData(List<RangeData> list, int value) {
....code....
}
当我有一个收入范围列表时出现问题,但我无法转换为RangeData列表。如果这是一个单项,那就没问题了。
List<IncomeRanges> incomes = xxx(); //returns the proper data.
//Yet this does not work.
findRangeData(incomes,55);
我试图对它进行各种演员表,但似乎没有任何效果。我怎样才能让它发挥作用?
答案 0 :(得分:10)
Java Generics是invariant。这意味着,给定两个具体的类A
和B
,SomeClass<A>
与SomeClass<B>
无关,即使B
是{{1}的子类型}}
因此,A
不是List<RangeData>
的超类型。相反,您应该使用upper bounded wildcard,如下所示:
List<IncomeRanges>
有关详细信息,请查看Generics, Inheritance, and Subtypes上的文档。
答案 1 :(得分:1)
为了扩展Anderson的答案,List<A>
和List<B>
是不相关的类型,即使B extends A
也是如此。要了解原因,请考虑如果List<B>
是List<A>
的子类,会发生什么。我们可以这样做:
class Animal{}
class Dog extends Animal{}
List<Dog> d = new List<Dog>();
((List<Animal>) a).add(new Animal()); //Uh oh
但这是一个问题,因为一个真正的Dog
列表包含一个非狗对象。
另一种方式呢?如果我们不能说List<B>
是List<A>
的子类,也许我们可以说List<A>
是List<B>
的子类。然而,这有相反的问题:
class Animal{}
class Dog extends Animal{}
class Cat extends Animal();
List<Animal> a = new List<Animal>();
a.add(new Cat());
Dog dog = ((List<Dog>) d).getFirst(); //Uh oh
但是我们从d中获取的元素不一定是Dog
- 在这种情况下,它是Cat
。所以这也是一个问题。
总而言之,Java中 mutable 集合的泛型类型(如List
s 不变 - List<A>
与{完全无关} {1}}无论List<B>
和A
之间的关系如何,如果有的话。{/ p>
正如安德森在答案中所做的那样,使用有界通配符可以解决这个问题。这确实限制了您允许执行的有效操作。例如,您无法向B
添加元素,因为无法保证您添加的元素是您要添加的列表的有效成员。但是,它打开了可以符合类型的列表的可能性。 List<? extends A>
和List<Cat>
虽然与List<Dog>
无关,但都是List<Animal>
的有效子类型。对于任何List<? extends Animal>
,从列表中检索的任何元素都将是Animal的一个实例(或者可能是其子类型之一)。