我正在为SCJP / OCPJP学习,我遇到了一个对我来说很奇怪的问题。
示例代码实例化了两个通用集合:
List<?> list = new ArrayList<?>();
List<? extends Object> list2 = new ArrayList<? extends Object>();
问题的“正确”答案是此代码将编译,但添加到任一集合都会产生运行时错误。
当我尝试编译这样的代码时,我只是得到错误。 Java教程甚至没有显示这种类型的代码,而是通常使用通配符作为upcast的一部分。
Collection<?> c = new ArrayList<String>();
上面的两个通用集合甚至是合法代码吗?我的逻辑中的第二个只会禁止接口。第一个看起来完全没用。为什么要使用不试图控制的泛型?
答案 0 :(得分:4)
查看优秀的Java generics tutorial PDF。更具体地说,关于通配符的部分包含您的问题的答案,我引用
Collection<?> c = new ArrayList<String>();
c.add( new Object() );
由于我们不知道
c
的元素类型代表什么,我们不能 添加对象。add()
方法接受E
类型的参数 集合的元素类型。当实际类型参数为?
时, 它代表一些未知的类型。我们传递给的任何参数都会 必须是这种未知类型的子类型。既然我们不知道是什么 类型,我们不能传递任何内容。唯一的例外是null
, 这是每种类型的成员。
答案 1 :(得分:2)
如果要在运行时声明Type,可以执行以下操作:
public class Clazz1<T> {
private final List<T> list = new ArrayList<T>();
private List<T> getList() {
return list;
}
/**
* @param args
*/
public static void main(String[] args) {
Clazz1<Integer> clazzInt = new Clazz1<Integer>();
clazzInt.getList().add(2);
System.out.println(clazzInt.getList());
Clazz1<String> clazzString = new Clazz1<String>();
clazzString.getList().add("test");
System.out.println(clazzString.getList());
}
}
答案 2 :(得分:1)
我在this回答之前对此做了一些回答。 ?
不能在实例化中使用。我不确定为什么它会说代码会编译,我用过的java编译器都不允许这样做。您可以通过以下方式执行上面显示的操作:
List<?> list = new ArrayList();
那会编译并运行,但你不能这样做:
list.add("hello world"); //This wouldn't compile
答案 3 :(得分:0)
new
生成对象的具体实例。具体实例只能有一种类型,包括任何泛型。知道这一点,通配符不能与new
一起使用。