泛型 - 下限/上限外卡行为?

时间:2017-05-22 12:11:23

标签: java generics

我试图了解下层和上层外卡的行为。

尝试编译以下代码时出现问题。

Collection<? extends Object> c = new ArrayList<Object>();
c.add(new Object()); // Compile time error

为了解决这个问题,我也尝试了下限外卡。幸运或不幸的是,代码编译得很好,但造成了很多混乱。

Collection<? super Object> c = new ArrayList<Object>();
 c.add(new Object()); // Compiles fine

有人可以解释一下,这两个代码片段是如何工作的。如果有人可以提供其他示例/链接,那就太好了。

如果我上面做错了,请纠正我。

提前致谢。

2 个答案:

答案 0 :(得分:7)

?表示&#34;未知类型&#34;。

Collection<? extends Object>表示某种类型对象的集合。这个&#34;某种类型&#34;可以是ObjectObject本身的子类的任何类型。究竟是哪种类型?编译器不知道。

当您尝试向集合中添加新的Object时,您无法做到。这是因为集合的类型未知。它可以是ArrayList<String>。它可以是HashSet<Integer>。所以编译器说

  

&#34;如果集合是ArrayList<String>怎么办?你不能在那里加Object!&#34;

基本上,编译器过于谨慎,不能让你这样做。

Collection<? super Object>表示某种类型对象的集合。这个&#34;某种类型&#34;可以是ObjectObject本身的超类的任何类型。它只能是一件事 - Object,因为Object没有超类。这就是为什么你可以在集合中添加新的Object的原因。

即使Object有超类,您仍然可以添加new Object()。让我们调用Object MyClass的超类。现在,该集合可以是MyClassObject的集合。无论哪个,您都可以添加Object

答案 1 :(得分:0)

让我们更改类类型,使其更容易理解。您的第一个示例已更改为Number

Collection<? extends Number> c = new ArrayList<Number>();

表示?类型中有Number个对象。所以它可以是extends Number例如IntegerDoubleFloatBigIntegerNumber等等。因此您无法保证列表中的List<Integer> // only allows Integer List<Double> // only allows Double List<Float> // only allows Float 对象位于哪个

<? extends Number>

这就是为什么你不能向<? super Number>添加任何内容的原因,因为它可能是上面的列表之一。

另一种方法是Number。 这意味着List中的每个对象都是Number的祖先。在这种情况下,您可以添加来自? super Number的超类型/类型的任何内容。您保证Number内部的所有内容都是list.get(0); // is a Number, but could be a Integer list.get(1); // is a Number, but could be a Float list.get(2); // is a Number, but could be a Double

但你不能保证的是实际的类型,例如

extends

tl; dr使用super进行阅读,<? super Number>进行添加。

以下是文档https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html

中的图表

enter image description here

以下是Jon Skeet对LibrariesSchema = new SimpleSchema({ 'books': { type: [BooksSchema], minCount: 1 } });

的解释

https://stackoverflow.com/a/8083260/4467208