我试图了解下层和上层外卡的行为。
尝试编译以下代码时出现问题。
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
有人可以解释一下,这两个代码片段是如何工作的。如果有人可以提供其他示例/链接,那就太好了。
如果我上面做错了,请纠正我。
提前致谢。
答案 0 :(得分:7)
?
表示&#34;未知类型&#34;。
Collection<? extends Object>
表示某种类型对象的集合。这个&#34;某种类型&#34;可以是Object
或Object
本身的子类的任何类型。究竟是哪种类型?编译器不知道。
当您尝试向集合中添加新的Object
时,您无法做到。这是因为集合的类型未知。它可以是ArrayList<String>
。它可以是HashSet<Integer>
。所以编译器说
&#34;如果集合是
ArrayList<String>
怎么办?你不能在那里加Object
!&#34;
基本上,编译器过于谨慎,不能让你这样做。
Collection<? super Object>
表示某种类型对象的集合。这个&#34;某种类型&#34;可以是Object
或Object
本身的超类的任何类型。它只能是一件事 - Object
,因为Object
没有超类。这就是为什么你可以在集合中添加新的Object
的原因。
即使Object
有超类,您仍然可以添加new Object()
。让我们调用Object
MyClass
的超类。现在,该集合可以是MyClass
或Object
的集合。无论哪个,您都可以添加Object
。
答案 1 :(得分:0)
让我们更改类类型,使其更容易理解。您的第一个示例已更改为Number
Collection<? extends Number> c = new ArrayList<Number>();
表示?
类型中有Number
个对象。所以它可以是extends Number
例如Integer
。 Double
,Float
,BigInteger
,Number
等等。因此您无法保证列表中的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
中的图表以下是Jon Skeet对LibrariesSchema = new SimpleSchema({
'books': {
type: [BooksSchema],
minCount: 1
}
});