为什么这是被允许的:
List<List<?>> list = new ArrayList<List<?>>()
但不包括这个?
List<?> list = new ArrayList<?>(); //Compile error: "Cannot instantiate the type ArrayList<?>"
如果使用未知泛型,就不能实例化对象,这就是为什么第二行会失败。
List<?> list = new ArrayList<String>();
将通用类型定义视为以下两个方面:
现在让我们将这种逻辑转化为非通用变量:
CharSequence val = new String("foo");
这是完全合法的。变量val
代表一种类型(2),当然永远不会直接实例化接口CharSequence
。但是,您可以将可分配的子类型分配给它,例如String
。您不能通过类似于new [? extends CharSequence]
的语句替换字符串的创建,必须明确命名要构造的类型。
现在让我们回到泛型,那里的事情也很相似。当您调用泛型类型的构造函数时。
new ArrayList<List<?>>()
你正在某种程度上构建一个泛型类型的新“类型实例”,在其中需要显式地为泛型定义中的类型变量 T
分配一个值,如 ArrayList<T>
。 ?
本身并没有描述 Java 类型,因此不能用作赋值值。但是,除了 T = ?
之外,定义 T = List<?>
是可能的,因为通配符可以是有效的 Java 类型定义的一部分。
在类型定义(1)中使用通配符时,例如
List<?> list
您并未构造一个新的泛型类型,而是仅仅描述了其中的边界。因此,在这种情况下可以使用通配符。