创建无界和有界外卡类型数组之间的区别?

gst*_*low 9 java arrays generics wildcard bounded-wildcard

为什么这段代码有效

ArrayList<?>[] arr = new ArrayList<?>[2];
Run Code Online (Sandbox Code Playgroud)

但以下两个不是?

ArrayList<? extends Object>[] arr = new ArrayList<? extends Object>[2];
ArrayList<? super Object>[] arr = new ArrayList<? super Object>[2];
Run Code Online (Sandbox Code Playgroud)

最后两行生成编译错误;

错误:通用数组创建.

请澄清差异.

更新

另一方面ArrayList<?>[] arr = new ArrayList<?>[2];编译好但是

ArrayList<?> arr = new ArrayList<?>();
Run Code Online (Sandbox Code Playgroud)

不.

Chr*_*s K 13

这里有一些问题,让我们依次看看每个问题:

  1. 类型绑定(即extends Object)只能在声明类型时声明,在实例化对象时不能使用它.

    例如

    ArrayList<? extends Object> ab = new ArrayList<? extends Object>(); // error ArrayList<? extends Object> ac = new ArrayList<String>(); // okay

  2. 数组不支持类型参数,例如:

    List<Integer>[] arrayOfLists = new List<Integer>[2]; // compile time error List<Integer> list = new List<Integer>(); // okay

    Oracle在此处记录了此限制的原因.

  3. <?>声明类型参数和数组时可以使用.添加它是为了在混合使用和不使用泛型的Java代码时帮助避免"未经检查的异常"错误.它意味着'未知的通用类型'.无界通配符的更多细节在这里.

    ArrayList<?>[] arr = new ArrayList<?>[2];

    由于上述原因有效.但是它的使用非常有限,因为只能将null赋给声明为的类型<?>.

    arr[0] = null; // compiles

    arr[1] = new Object(); // compile time error

    Oracle提供了以下有关使用通配符的指南,这将有助于了解何时使用此通配符.

  4. <?>不能用于实例化对象.例如

    ArrayList<?> arr = new ArrayList<?>(); // does not compile

    ArrayList<?> arr2 = new ArrayList<>(); // but this does

    ArrayList<?> arr3 = new ArrayList<String>(); // and so does this

    但是仍然存在使用<?>仅接受null 的问题.

    arr3.add( " " ); // does not compile even though it was instantiated with String

    arr3.add( null ); // compiles just fine