考虑以下代码:
List<? extends Integer> lst= new ArraList<Integer>();
lst.add(5);//Compile error
lst.get(5);//OK
在第二个字符串中我们有编译错误,因为我们必须保证在所有潜在的子类型中都有方法 add(int)List<? extends Integer>
并且编译器知道它null
唯一,第三个字符串返回未知类型并且编译器将他转换为 Object,不是吗?
List<? super Integer> lst= new ArrayList<Integer>();
lst.add(5);// No Compile error
该列表现在是一个消费者,您将对象放入其中......
还有这个
lst.get(5);
是一个不同的蛋糕......您提供了您想要获取的整数索引......(更不用说Sotirios提到的:返回类型将Object
在这种情况下。此外,在这个角色中,列表是一个提供者。 ..)
除了由通配符限制的范围之外,您无法添加任何内容,因为您永远不知道基础null
类型。List
List<? extends Integer> lst= new ArrayList<Integer>();
lst.add(5); // Compile error
lst.get(5); // 5 is just the index
但是,您可以获得一个元素,因为您知道它必须是一个Integer
(在这种情况下)。
很难解释,Integer
因为它是一个无法扩展的类。但是拿这个
public class Foo {}
public class Bar extends Foo {}
public class Zoop extends Foo {}
你可以添加什么
List<? extends Foo> fooList = new ArrayList<Zoop>(); // could come from a method
?
该列表被声明为? extends Foo
即使运行时对象的泛型类型是Zoop
. 因此编译器不能让你添加任何东西。但是您可以保证对Foo
对象进行操作,因此您可以很好地检索它们。
一旦你有了 a List<? extends Integer>
,编译器就不知道它Integer
是子类型还是子类型。编译器无法确保添加任何内容的类型安全性null
(实际上,将任何内容传递给采用泛型类型参数的方法,包括add
方法),因此它不允许这样做。尽管存在Integer
且final
不允许子类,但仍会发生这种情况。
对于该get
方法,编译器知道返回类型是某种Integer
,因此它允许调用并将隐式强制转换为Integer
。