将对象列表强制转换为超类型列表

时间:2015-04-13 18:05:46

标签: java generics casting

我有以下类结构:

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);

我试图对它进行各种演员表,但似乎没有任何效果。我怎样才能让它发挥作用?

2 个答案:

答案 0 :(得分:10)

Java Generics是invariant。这意味着,给定两个具体的类ABSomeClass<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的一个实例(或者可能是其子类型之一)。