繁体   English   中英

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

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

我知道我们不能在列表中添加扩展边界类型的元素。 但我仍然不确定为什么 java 编译器不允许这样做。 因为编译器可以很容易地检查添加的新元素是否是 Generic 类型的子类型。 任何人都可以帮我解决这个问题吗?

这种情况称为协方差, extends关键字允许您从Collection读取元素,但不能添加它们。 这是因为编译器将add操作视为不安全。 例如,您可以声明以下任何列表:

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

您可以毫无问题地读取它们,因为无论列表包含什么,都可以向上转换为Number 但是,您不得将任何内容放入其中:

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

这是因为编译器无法确定泛型列表的实际类型(在我们的示例中可能是IntegerFloatDouble )。 因此,这是一个不安全的操作,您可能将Long添加到Integer列表,因此编译器不允许您这样做。

阅读这篇文章以获得更深入的解释。

我将使用对这里示例的修改:

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.

您非常正确地指出“编译器可以轻松检查添加的新元素是否是泛型类型的子类型”。 但即便如此,由于编译器无法确定列表l的类型,接受l.add(l, new Object())将导致列表ls损坏。

因此编译器正在做它的工作,它比运行时检查更早地捕获错误。

暂无
暂无

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

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