用于 '?延伸'和'?超级'收集泛型

时间:2012-09-26 14:51:09

标签: java generics collections

任何人都可以解释为什么我们在?泛型中使用Collection

例如:

 List<? extends Number> numberlist;
 List<? super Integer> numberlist;

7 个答案:

答案 0 :(得分:25)

通配符引入了如何使用集合的限制。

例如,对于List<? extends Number>,我无法在列表中添加新元素。这是因为我所知道的是列表是Number的某种子类型,但我不知道实际的子类型是什么(所以我怎么知道要添加什么?)。例如,请使用以下代码:

public void doSomethingWith(List<? extends Number> numbers) {
    numbers.add(Integer.valueOf(0)); // Won't compile
}

这不会编译,因为这些方法调用都是合法的:

doSomethingWith(new ArrayList<Integer>());
doSomethingWith(new ArrayList<Double>());

可以做的是从列表中读取元素:

// This will all compile
public void doSomethingWith(List<? extends Number> numbers) {
    for (Number number : numbers) {
        // Do something with number
    }
    // OR
    Number number = numbers.get(0);
    // OR
    Number number = numbers.remove(0);
}

调用get之类的方法会返回某种Number,我们知道因为? extends Number而导致事实,因此我们可以将其视为阅读目的。< / p>

另一方面,List<? super Integer>具有完全相反的结果。我不能再从列表中读取,但我可以写信给它。我知道无论?是什么,它肯定是Integer的超类,所以列表的具体类型肯定会接受Integer值。例如:

public void doSomethingWith(List<? super Integer> integers) {
    integers.add(Integer.valueOf(0));
}

该代码完全合法。但是,如果要从列表中读取,唯一的方法是使用Object,因为其他任何需要强制转换(需要知道其具体类型):

for (Object obj : integers)
// OR
Object obj = integers.get(0);
// OR
Object obj = integers.remove(0);

真正发生的事情

这是实际发生的事情。当您指定? extends Number时,您将使用元素作为参数无法使用的任何方法。实际上,如果您尝试使用List<? extends Number>上的Ctrl + Space在Eclipse中自动完成代码,则会在null方法等中显示add作为参数的类型。同时,返回元素的所有方法都保证至少返回某种Number,尽管你不确切知道它实际上是哪个Number的子类。

当您指定? super Integer时,您将使用采用元素作为参数的任何方法保证他们接受Integer值(以及{的子类{1}}。这允许您调用Integer之类的方法,因为您知道它们会接受add类型。同时,所有返回元素的方法只能保证返回某些,但我们不知道是什么,所以返回元素的所有方法都只保证返回{{ 1}}。

PECS是记住这一点的优秀首字母缩略词,它意味着“ P roducer E xtends, C onsumer S upers”。这意味着如果您希望列表为您提供某些内容,那么它就是生产者,您应该使用Integer。如果您希望列表接受来自您的内容,那么它就是消费者,因此您使用Object。有关详情,请参阅this answer

但是如果我有一个没有边界的通配符怎么办?

两者兼得! extends限制您调用将泛型类型作为参数的方法,而会导致返回泛型类型的所有方法返回super。这是因为我们不知道这种类型是什么。例如,<?>中的所有这些分配都是合法的:

Object

等等。

答案 1 :(得分:2)

它是一个通配符。 ?表示从数字继承或者是Integer类的超类的任何类都可以工作。希望这可以帮助。 :)

答案 2 :(得分:2)

当您在扩展超级之间学习通配符和差异时,只需记住PECS即可。这条规则的所有内容都非常简单易记。

答案 3 :(得分:1)

?用于在使用泛型时定义wild cards

示例中的语句告诉List接受Number

类型的任何对象

答案 4 :(得分:1)

?表示任何课程

? extends MyClass

表示MyClass或MyClass本身的任何子类。

答案 5 :(得分:1)

以下是我要说的:

List<? extends Number> numberlist; //Any class that is extended from Number class,  for example Integer, BigInt, ... may come

List<? super Integer> numberlist; //Any class that Integer class is extended from. Here for example Number may come

因为:

Integer extends Number{
}

答案 6 :(得分:0)

List<? extends Number>List<Number>都允许添加例如整数,但是: 使用List<Number>,你可以放入整数和其他任何“是”数字。使用List<? extends Number>,您只能输入一个具体的运行时类型。是它的整数,那么你就不能添加另一种也是数字的类型。