Shr*_*ari 5 java generics collections
任何人都可以解释我们?在Collection泛型中使用的原因.
例如:
List<? extends Number> numberlist;
List<? super Integer> numberlist;
Run Code Online (Sandbox Code Playgroud)
Bri*_*ian 26
通配符引入了如何使用集合的限制.
例如,List<? extends Number>我不能在列表中添加新元素.这是因为我所知道的是列表是某种子类型Number,但我不知道实际的子类型是什么(所以我怎么知道要添加什么?).例如,请使用以下代码:
public void doSomethingWith(List<? extends Number> numbers) {
numbers.add(Integer.valueOf(0)); // Won't compile
}
Run Code Online (Sandbox Code Playgroud)
这不会编译,因为两者的这些方法调用是合法的:
doSomethingWith(new ArrayList<Integer>());
doSomethingWith(new ArrayList<Double>());
Run Code Online (Sandbox Code Playgroud)
你可以做的是从列表中读取元素:
// 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);
}
Run Code Online (Sandbox Code Playgroud)
对类似方法的调用get将返回某种类型Number,我们知道因为这个事实? extends Number,因此我们可以将其视为用于阅读目的.
另一方面,List<? super Integer>恰恰相反.我不能再从列表中读取,但我可以写信给它.我知道无论如何?,它肯定会是一个超类Integer,所以列表的具体类型肯定会接受Integer值.例如:
public void doSomethingWith(List<? super Integer> integers) {
integers.add(Integer.valueOf(0));
}
Run Code Online (Sandbox Code Playgroud)
该代码完全合法.但是,如果要从列表中读取,唯一的方法是使用,Object因为其他任何需要强制转换(需要知道其具体类型):
for (Object obj : integers)
// OR
Object obj = integers.get(0);
// OR
Object obj = integers.remove(0);
Run Code Online (Sandbox Code Playgroud)
什么是真正发生的
这是实际发生的事情.当您指定时? extends Number,您正在制作任何将元素作为参数不可用的方法.实际上,如果您尝试使用Ctrl + Space在Eclipse中自动完成代码List<? extends Number>,它会null在add方法等中显示为参数的类型.同时,所有返回元素的方法都保证至少返回某种类型Number,尽管你不确切知道Number它实际上是哪个子类.
当你指定时? super Integer,你正在制作任何方法,它将元素作为参数保证它们将接受Integer值(以及它们的子类Integer).这允许您调用方法,add因为您知道它们将接受Integer类型.同时,所有返回元素的方法只能保证返回一些东西,但我们不知道是什么,所以返回元素的所有方法都只能保证返回Object.
佩奇是一个很好的缩写,记住这一点,它的意思是" P roducer ê xtends,Ç onsumer 小号 upers".这意味着如果您希望列表为您提供某些内容,那么它就是生产者,您应该使用它extends.如果您希望列表接受来自您的内容,那么它就是消费者,因此您可以使用super.请参阅此答案了解更多信息
但是,如果我有一个没有边界的通配符怎么办?
它做到了!<?>限制您打电话的是采取泛型类型作为参数的方法,并导致所有返回的泛型类型返回方法Object.这是因为我们不知道这种类型是什么.例如,所有这些分配到a中List<?>都是合法的:
List<?> list;
list = new ArrayList<Integer>();
list = new ArrayList<String>();
list = new ArrayList<MyClass>();
Run Code Online (Sandbox Code Playgroud)
等等.