我是java的新手,我有这样的代码:
List<? extends Object> k = new ArrayList<Integer>();
k.add(new Integer(1));
我收到的错误如下:
Error:(13, 10) java: no suitable method found for add(java.lang.Integer)
method java.util.Collection.add(capture#1 of ? extends java.lang.Object) is not applicable
(argument mismatch; java.lang.Integer cannot be converted to capture#1 of ? extends java.lang.Object)
method java.util.List.add(capture#1 of ? extends java.lang.Object) is not applicable
(argument mismatch; java.lang.Integer cannot be converted to capture#1 of ? extends java.lang.Object)
我几乎没有问题:
List<? extends Object> k = new ArrayList<Integer>();
为什么在等式的右边不允许我放new ArrayList<? extends Object>()
?
<? extends Object>
表示任何类扩展Object
对吗?所以在java中,所有类都扩展Object
,所以我为什么会遇到错误:
k.add(new Integer(1));
new ArrayList<Integer>()
,但允许我添加Integer
为什么?提前致谢。
答案 0 :(得分:4)
尽管在声明时,java允许我提供新的
ArrayList<Integer>
。
是。但是,它还允许您分配ArrayList<String>
。
由于您不知道列表应存储的内容,因此无法添加任何内容(null
除外)。
答案 1 :(得分:0)
是的,欢迎使用java破解的通用系统。问号作为类型参数意味着“未知类型”。声明List<T>.add
接受T
类型的参数。所以,在你的情况下,它应该是未知的。因为Integer的类型是已知的,所以你不能这样称呼它。
为什么要使用问号作为类型参数呢?好吧,有时候,列表元素的具体类型并不重要,你只关心类型边界。 例如:
public void printDoubles(List<? extends Number> l) {
for(Number n : l) System.out.println(n.doubleValue() * 2);
}
这可以仅用List<Number>
来完成吗?好吧,事实证明,它不能,因为java中的列表(和一般的容器)在它们的元素类型上不是协变的(实际上有一个原因)。这意味着List<Integer>
不是List<Number>
的子类,因此,如果声明上面的函数接受List<Number>
类型的参数,那么它将是相当无用的,因为你无法通过没有强制转换的整数(或任何其他数字类型)列表。
所以,为了解决这个问题,他们发明了问号。该声明实际上等同于<T extends Number> public void printDoubles(List<T> l)
,除了它使读者更清楚,该函数特别关注列表元素的特定具体类型。