有人可以解释一下<是什么吗?超级T>意味着什么,什么时候应该使用它,以及这种结构应该如何与<T>和<合作?扩展 T>?

2022-09-02 13:32:21

我使用泛型相当长的时间,但我从未使用过像.List<? super T>

这是什么意思?如何使用它?擦除后的外观如何?

我也想知道:它是泛型编程(模板编程?)的标准,还是它只是Java的“发明”?例如,c#是否允许类似的结构?


答案 1

当您希望将一个集合中的项用于另一个集合时,将使用此构造。例如,您有一个泛型,并且想要添加一个方法,该方法将集合作为参数,并将堆栈中的所有项弹出到其中。根据常识,此代码应该是合法的:StackpopAll

Stack<Number> numberStack = new Stack<Number>();
Collection<Object> objects = ... ;
numberStack.popAll(objects);

但它只有在你像这样定义时才会编译:popAll

// Wildcard type for parameter that serves as an E consumer
public void popAll(Collection<? super E> dst) {
    while (!isEmpty())
    dst.add(pop());
}

硬币的另一面是应该这样定义:pushAll

// Wildcard type for parameter that serves as an E producer
public void pushAll(Iterable<? extends E> src) {
    for (E e : src)
    push(e);
}

更新:Josh Bloch 传播此助记符,以帮助您记住要使用的通配符类型:

PECS代表生产者扩展,消费者超级

有关更多详细信息,请参见《有效的 Java 第 2 版》第 28 项


答案 2

这称为“有界通配符”。这在官方教程中得到了很好的解释。

如教程中所述,因此您知道该列表仅包含一个子类型的对象T

例如,可以只保存 s 或仅 s,但不能同时保存两者。List<? extends Number>IntegerLong


推荐