用于 '?延伸'和'?超级“在集合泛型 [英] Use of '? extends ' and '? super ' in Collection generics

查看:96
本文介绍了用于 '?延伸'和'?超级“在集合泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何人都可以解释为什么我们使用?

Can anybody explain why we use ? in Collection generics.

例如:

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


推荐答案

通配符对如何使用集合。

The wildcards introduce restrictions in how the collection can be used.

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

For example, with List<? extends Number>, I can't add new elements to the list. This is because all I know is that the list is some kind of subtype of Number, but I don't know what that actual subtype is (so how could I know what to add?). For example, take the following code:

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

>这些方法调用是合法的:

This won't compile because both of these method calls are legal:

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 ,我们知道因为的事实?

Calls to methods like get will return some kind of Number, we know that for a fact because of the ? extends Number, so we can treat it like that for reading purposes.

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

On the other hand, List<? super Integer> has exactly the opposite result. I can no longer read from the list, but I can write to it. I know that whatever ? is, it will definitely be a super-class of Integer, so concrete types of the list will definitely accept Integer values. For example:

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

这段代码是完全合法的。但是,如果你想从列表中读取,唯一的方法是使用 Object ,因为任何东西都需要转换(这需要知道它的具体类型):



That code is completely legal. However, if you want to read from the list, the only way to do this is to use Object since anything else requires casting (which requires knowing its concrete type):

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

真正发生的事

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

Here's what's actually happening. When you specify ? extends Number, you're making any method that takes elements as a parameter unusable. In fact, if you try to auto-complete code in Eclipse using Ctrl+Space on a List<? extends Number>, it shows null as the parameters' types in the add methods and the like. Meanwhile, all the methods that return elements are guaranteed to return at least some kind of Number, though you won't know exactly which subclass of Number it might actually be.

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

When you specify ? super Integer, you're making any method that takes elements as a parameter guarantee that they'll accept Integer values (and sub-classes of Integer as well). This allows you to call methods like add since you know they'll accept Integer types. Meanwhile, all methods that return elements are only guaranteed to return something, but we don't know what, so all the methods that return elements are only guaranteed to return Object.

PECS是一个很好的首字母缩写,记住这一点,它意味着 b> E xtends, C onsumer S upers。这意味着如果你想让你的列表给你一些东西,它是一个生产者,你应该使用 extends 。如果你希望你的列表接受你的东西,它是一个消费者,所以你使用 super 。有关详情,请参见此答案

PECS is an excellent acronym to remember this, it means "Producer Extends, Consumer Supers". This means that if you want your list to give you something, it's a producer, and you should use extends. If you want your list to accept things from you, it's a consumer, so you use super. See this answer for more.

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

<?> 限制您调用以泛型类型作为参数的方法导致所有返回通用类型的方法返回 Object 。这是因为我们不知道什么类型是什么。例如,列表<?> 中的所有这些分配都是合法的:

It does both! <?> restricts you from calling methods that take the generic type as an argument and causes all the methods that return the generic type to return Object. This is because we have no idea what the type is whatsoever. For example, all of these assignments into a List<?> are legal:

List<?> list;
list = new ArrayList<Integer>();
list = new ArrayList<String>();
list = new ArrayList<MyClass>();

等等。

这篇关于用于 '?延伸'和'?超级“在集合泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆