“< ? extends E >”的用途是什么?(涉及IT技术)

3

当我使用泛型时,我遇到了声明 < ? extends E> 。 如果以集合接口的addAll方法为例。

它的声明如下:

   interface Collection<E> {
      public boolean addAll(Collection<? extends E> c);
  }

从addAll的声明中,我理解(从不同来源阅读所得):

  • ? extends E 表示可以添加具有任何E子类型元素的集合的所有成员

下面我们来看一个例子:

List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);

List<? extends Number> nums = ints; // now this line works
/*
 *without using ? syntax above line did not use to compile earlier 
 */
List<Double> doubleList = new ArrayList<Double>();
doubleList.add(1.0);
nums.addall(doubleList); // compile time error 

错误:

方法addall(List< Double >)在类型为List< capture#1-of ? extends Number >的列表中未定义

我也在O'Reilly的《Java Generics and Collections》中读到过:

一般来说,如果一个结构包含了类型形式为? extends E的元素,我们可以从该结构中获取元素,但是我们不能将元素放入该结构中。

所以我的问题是,当我们不能使用这个来修改东西时,它有什么用处?只是为了从该集合中获取元素,如果它是一个子类型吗?


你尝试过搜索吗?这个问题肯定已经被问过了。 - Henry
1
是的,我知道。但是没有问题涵盖了我所问的内容,我知道通配符的用法,但我的问题是为什么在我们无法添加/更改现有集合时还要使用它。 - hellrocker
我没有得到任何编译错误。 - Naga Vemprala
2个回答

4
所以我的问题是如果我们不能用它来修改这个东西,那么它的用途是什么?只是从这个集合中获取元素如果它是一个子类型?
是的,你说得对。只是用来从中获取元素。
请记住,Collection<? extends Number> 是“变量”的类型,而不是集合本身的类型。通配符语法的含义更像是特定集合必须匹配的模式,而不是类型以“对象X是类型T”的意义。
如果Java没有通配符,你将非常受限制在你可以表达的内容上。例如,泛型addAll方法只能接受完全相同组件类型的集合。

3
这意味着addAll方法允许添加任何扩展E类的对象集合。例如,如果G扩展了E,则可以将一个G数组添加到此集合中。

1
我认为add不是那样工作的。你不能将一个G类型的数组添加到这个集合中。从技术上讲,通过声明<? extends E>,你使得这个集合是不可变的。马尔科·托波尼克先生,我说得对吗? - Naga Vemprala
1
我能清楚地看到的唯一事情是从集合类(Collections class)使用 Sort 方法。Collections 实现了静态类(static classes)。Sort 是其中之一,其语法为:public static <T extends Comparable<? super T>> void sort(List<T> list)。如果我们不实现 Comparable,则无法在此处使用 SORT。 - Naga Vemprala

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接