Generics - lower/ upper bound wild card behaviour?
我试图了解下界和上界通配符的行为。
在尝试编译以下代码时遇到问题。
1 2
| Collection <? extends Object > c = new ArrayList <Object >();
c. add(new Object()); // Compile time error |
为了解决这个问题,我还简单地尝试了下界通配符。幸运的是,或者不幸的是,代码编译得很好,但是造成了很多混乱。
1 2
| Collection <? super Object > c = new ArrayList <Object >();
c. add(new Object()); // Compiles fine |
有人能解释一下这两个代码片段是如何工作的吗?如果有人能提供更多的示例/链接,那就太好了。
如果我在上面做了什么错误,请纠正我。
事先谢谢。
?表示"未知类型"。
Collection extends Object>表示某种对象的集合。这个"某些类型"可以是Object或Object本身的子类的任何类型。哪种类型?编译器不知道。
当您试图向集合中添加新的Object时,您不能这样做。这是因为集合的类型未知。它可以是一个ArrayList。它可以是一个HashSet。所以编译器说
"What if the collection is ArrayList? You can't put an Object in there!"
基本上,编译器过于谨慎,不允许您这样做。
Collection super Object>表示某种对象的集合。这种"某种类型"可以是任何一种类型,它本身就是Object或Object的超类。这里只有一件事——Object,因为Object没有超类。这就是为什么你可以在收藏中添加一个新的Object。
即使Object有一个超类,您仍然可以添加new Object()。我们称之为ObjectMyClass的超类。现在,集合可以是MyClass或Object的集合。无论是哪种情况,您都可以在其中添加一个Object。
- 我完全理解关于Collection extends Object>的部分,这是有道理的。但是,如果是Collection super Object>,那么接受任何SupersClass或Object类的原因是什么?
- 那就是什么?超级物体意味着。如果a扩展b,可以将b添加到a的集合中。这里的情况相同。@ Yahya
- @乔恩弗尼,哦,这是个打字错误。我的意思是你可以把A添加到B的集合中。
- @清洁工谢谢,我明白你的意思了。我认为你的最后一段解释得很好。但在你的脑子里很难看到。
让我们更改类类型,使其更易于理解。你的第一个例子改为Number。
1
| Collection<? extends Number> c = new ArrayList<Number>(); |
表示存在来自类型Number的?对象。因此,它可以是extends Number的任何对象,例如Integer、Double、Float、BigInteger等,因此您不能保证列表中存在哪种Number对象,因为
1 2 3
| List<Integer> // only allows Integer
List<Double> // only allows Double
List<Float> // only allows Float |
这就是为什么你不能添加任何东西到 extends Number>中的原因,因为它可能是上面的列表之一。
另一种方法是使用 super Number>。这意味着列表中的每个对象都是Number的祖先。在这种情况下,您可以添加Number的父类型/类型中的任何内容。你向? super Number保证里面的东西都是Number。
但你不能保证的是实际类型,例如
1 2 3
| 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 |
tl;dr使用extends进行读取,super进行添加。
下面是来自docs https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html的图表
这是乔恩·斯基特对埃多克斯的解释。
https://stackoverflow.com/a/8083260/4467208
- 关于? super的部分需要工作。大部分都是向后的。如果绑定为? super Number,则无法执行Integer、Float和Double。
- @但这些类型是一个Number。它们不一定需要是超级类型。
- Integer是Number的一个子类。? super Number匹配超类(或Number本身)。Number的唯一超类是Object。
- @约翰克尔曼是的,这些是数字,例如ideone.com/fu5rvt