实例化泛型:新的ArrayList <! - ? - >()vs new ArrayList <list <?>&gt;()</list <?>

时间:2014-03-05 12:11:21

标签: java generics

为什么允许这样做:

List<List<?>> list = new ArrayList<List<?>>()

但不是吗?

List<?> list = new ArrayList<?>(); //Compile error: "Cannot instantiate the type ArrayList<?>"

3 个答案:

答案 0 :(得分:3)

创建ArrayList时,需要定义它将包含的对象类型:

  • 在第一个示例中,您创建一个ArrayList,其中包含未知泛型类型的列表,但它们都将是列表。
  • 在第二个示例中,您尝试创建一个未知类型的ArrayList,这是不允许的。

答案 1 :(得分:1)

您无法实例化具有未知泛型的对象,这就是第二行失败的原因。

List<?> list = new ArrayList<String>();

然而,当使用“列表”时,代码将无法知道它是一个字符串列表,使其相当无用。

第一次调用有效,因为您指定要创建其他列表的数组列表,这些列表将在您实际实例化子列表时确定。在这里,您只实例化父列表,它实际上是列表列表。

答案 2 :(得分:0)

将泛型类型定义视为两者

  1. 某种构造函数的定义,用于创建泛型类型的新非泛型“类型实例”。
  2. 类型定义。
  3. 现在让我们将这个逻辑转换为非泛型变量:

    CharSequence val = new String("foo");
    

    完全合法。变量val表示类型(2),当然永远不会是接口CharSequence的直接实例。但是,您可以构造(1)此类型,但您可以为其指定可分配的子类型,例如String。您既不能通过声明类似new [? extends CharSequence]的内容来替换字符串的创建,也需要明确命名要构造的类型。

    现在让我们回到事物相似的泛型。当您调用泛型类型的构造函数时。

    new ArrayList<List<?>>()
    

    您正在构建构建(2)泛型类型的新“类型实例”,您需要在通用定义的类型变量T中显式指定值在ArrayList<T>?本身并不描述Java类型,因此不能用作赋值。但是,除了T = ?之外,定义T = List<?>是可能的,因为通配符可以是有效Java类型定义的一部分。

    类型定义(1)中使用通配符时,如

    List<?> list
    

    你不是构建一个新的泛型类型,你只是在描述一个类型的界限。因此,可以在这种情况下使用通配符。