我知道我们无法在列表中添加元素,这是扩展边界的类型。但我仍然不确定为什么java编译器不允许这样做。因为编译器可以很容易地检查添加新元素是否是Generic类型的子类型。有人可以帮我这个吗?
答案 0 :(得分:1)
此案例称为协方差,extends
关键字允许您从Collection
读取元素,但不能添加它们。这是因为编译器将add
操作视为不安全。例如,您可以声明以下任何列表:
List<? extends Number> myNums = newArrayList<Integer>();
List<? extends Number> myNums = newArrayList<Float>();
List<? extends Number> myNums = newArrayList<Double>();
您可以毫无问题地从中读取,因为无论列表包含什么,都可以上传到Number
。但是,您不能将任何内容放入任何内容中:
myNums.add(45L); //compiler error
这是由于编译器无法确定通用列表的实际类型(可能是Integer
,Float
或Double
在我们的示例中) 。因此,这是一个不安全的操作,您可能会在Long
列表中添加Integer
,因此编译器不允许您这样做。
阅读this文章以获得更深入的解释。
答案 1 :(得分:0)
我将使用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.
您非常正确地指出“编译器可以轻松检查添加新元素是否是Generic类型的子类型”。但即便如此,由于编译器无法确定列表l
的类型,因此接受l.add(l, new Object())
会导致列表ls
损坏。
因此编译器正在完成它的工作,它比运行时检查更早地捕获错误。