简体   繁体   English

为什么我们不能使用扩展边界在 java 泛型中添加元素?

[英]Why we cant add the elements in java generics using extends bounds?

I understand we can't add the element on the list which is the type of the extends bounds.我知道我们不能在列表中添加扩展边界类型的元素。 But I am still not sure why the java compiler doesn't allow this.但我仍然不确定为什么 java 编译器不允许这样做。 since the compiler can easily check that whether the adding new element is the subtype of the Generic type.因为编译器可以很容易地检查添加的新元素是否是 Generic 类型的子类型。 Can anyone please help me on this?任何人都可以帮我解决这个问题吗?

This case is called Covariance, the extends keyword allows you to read elements from a Collection , but not to add them.这种情况称为协方差, extends关键字允许您从Collection读取元素,但不能添加它们。 This is because the compiler treats the add operation as unsafe.这是因为编译器将add操作视为不安全。 For instance, you could declare any of the following lists:例如,您可以声明以下任何列表:

List<? extends Number> myNums = new ArrayList<Integer>(); 
List<? extends Number> myNums = new ArrayList<Float>(); 
List<? extends Number> myNums = new ArrayList<Double>();

You would be able to read from them without problems, because whatever the list contains, can be upcasted to Number .您可以毫无问题地读取它们,因为无论列表包含什么,都可以向上转换为Number However, you are not allowed to put anything into any of them:但是,您不得将任何内容放入其中:

myNums.add(45L); //compiler error

This is due to the compiler not being able to determine the actual type of the of the generic list (could be of Integer , of Float or of Double in our example).这是因为编译器无法确定泛型列表的实际类型(在我们的示例中可能是IntegerFloatDouble )。 This is therefore an unsafe operation, you could be adding a Long to an Integer list, so the compiler doesn´t allow you.因此,这是一个不安全的操作,您可能将Long添加到Integer列表,因此编译器不允许您这样做。

Read this article for a deeper explanation.阅读这篇文章以获得更深入的解释。

I'll use a modification of an example from here :我将使用对这里示例的修改:

List<String> ls = new ArrayList<String>();
List<? extends Object> l = ls;
l.add(l, new Object()); // not legal - but assume it was!
String s = ls.get(0); // ClassCastException - ls contains
                      // Objects, not Strings.

You pointed very correctly that "the compiler can easily check that whether the adding new element is the subtype of the Generic type".您非常正确地指出“编译器可以轻松检查添加的新元素是否是泛型类型的子类型”。 But even so, since the compiler can not determine the type of the list l , accepting l.add(l, new Object()) will cause a corruption of list ls .但即便如此,由于编译器无法确定列表l的类型,接受l.add(l, new Object())将导致列表ls损坏。

Thus the compiler is doing its job, it catches errors earlier than a run-time checking does.因此编译器正在做它的工作,它比运行时检查更早地捕获错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM