用于 ‘? 延伸’和’? super’in Collection generics
谁能解释我们使用的原因?
在Collection
generics。
例如:
List numberlist; List numberlist;
通配符引入了如何使用集合的限制。
例如,使用List extends Number>
List extends Number>
,我无法在列表中添加新元素。 这是因为我所知道的是列表是Number
某种子类型,但我不知道实际的子类型是什么(所以我怎么知道要添加什么?)。 例如,请使用以下代码:
public void doSomethingWith(List extends Number> numbers) { numbers.add(Integer.valueOf(0)); // Won't compile }
这将无法编译,因为这两个方法调用都是合法的:
doSomethingWith(new ArrayList()); doSomethingWith(new ArrayList());
你可以做的是从列表中读取元素:
// 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
? extends Number
,所以我们可以像阅读一样对待它。
另一方面, List super Integer>
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
? extends Number
,你正在制作任何将元素作为参数不可用的方法。 实际上,如果您尝试使用List extends Number>
上的Ctrl + Space在Eclipse中自动完成代码List extends Number>
List extends Number>
,它在add
方法等中显示null
作为参数的类型。 同时,所有返回元素的方法都保证至少返回某种Number
,尽管你不会确切地知道它实际上是哪个Number
子类。
当你指定? super Integer
? super Integer
,你正在制作任何以元素作为参数的方法,保证它们接受Integer
值(以及Integer
子类)。 这允许你调用像add
这样的方法,因为你知道它们会接受Integer
类型。 同时,所有返回元素的方法只保证返回一些东西 ,但我们不知道是什么,所以返回元素的所有方法都只能保证返回Object
。
PECS是一个很好的首字母缩略词,它记住了这一点,它意味着“ P roducer E xtends, C onsumer S upers”。 这意味着如果你想让你的列表给你一些东西,它就是一个制作人,你应该使用extends
。 如果你希望你的列表接受你的东西,它是一个消费者,所以你使用super
。 请参阅此答案了解更多信息
但是,如果我有一个没有边界的通配符怎么办?
它做到了! >
限制您调用将generics类型作为参数的方法,并使返回generics类型的所有方法返回Object
。 这是因为我们不知道这种类型是什么。 例如,所有这些分配到List>
都是合法的:
List> list; list = new ArrayList(); list = new ArrayList(); list = new ArrayList();
等等。
它是一个通配符。 ? 表示从数字inheritance或者是Integer类的超类的任何类都可以工作。 希望这可以帮助。 🙂
当你学习通配符和扩展和超级之间的差异时,只需记住PECS 。 这条规则的所有内容都非常简单易记。
?
用于在使用generics时定义通配符 。
您在示例中的语句告诉List接受任何Number
类型的对象
?
意思是任何一类
? extends MyClass
表示MyClass或MyClass本身的任何子类。
这就是我要说的:
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{ }
List extends Number>
List extends Number>
和List
都允许添加例如Integers,但是:使用List
你可以放入Integers和其他任何“is”数字。 用List extends Number>
List extends Number>
你只能在其中放入一个具体的运行时类型。 它是整数,那么你不能添加另一个也是数字的类型。