创建一个数组以在Java中存储泛型类型

Gee*_*eek 39 java generics

假设我必须创建一个存储整数ArrayList的数组,数组大小为10.

以下代码将执行此操作:

ArrayList<Integer>[] pl2 = new ArrayList[10]; 
Run Code Online (Sandbox Code Playgroud)

问题1:

在我看来,更合适的代码

ArrayList<Integer>[] pl2 = new ArrayList<Integer>[10];    
Run Code Online (Sandbox Code Playgroud)

为什么这不起作用?

问题2:

以下两个编译

  1. ArrayList<Integer>[] pl2 = new ArrayList[10];
  2. ArrayList[] pl3 = new ArrayList[10];

就参考声明而言pl2,pl3有什么区别?

lte*_*ean 16

通用信息仅在编译时很重要,它告诉编译器可以将哪种类型放入数组中,在运行时,所有通用信息都将被删除,因此重要的是如何声明泛型类型.

引自Think in Java:

说你不能创建泛型类型的数组并不完全正确.没错,编译器不会让你实例化泛型类型的数组.但是,它将允许您创建对此类数组的引用.例如:

List<String>[] ls; 
Run Code Online (Sandbox Code Playgroud)

这无需投诉就可以通过编译器.虽然您无法创建一个包含泛型的实际数组对象,但您可以创建一个非泛型类型的数组并将其强制转换:

//: arrays/ArrayOfGenerics.java 
// It is possible to create arrays of generics. 
import java.util.*; 

public class ArrayOfGenerics { 
    @SuppressWarnings("unchecked") 
    public static void main(String[] args) { 
        List<String>[] ls; 
        List[] la = new List[10]; 
        ls = (List<String>[])la; // "Unchecked" warning 
        ls[0] = new ArrayList<String>(); 
        // Compile-time checking produces an error: 
        //! ls[1] = new ArrayList<Integer>(); 

        // The problem: List<String> is a subtype of Object 
        Object[] objects = ls; // So assignment is OK 
        // Compiles and runs without complaint: 
        objects[1] = new ArrayList<Integer>(); 

        // However, if your needs are straightforward it is 
        // possible to create an array of generics, albeit 
        // with an "unchecked" warning: 
        List<BerylliumSphere>[] spheres = 
           (List<BerylliumSphere>[])new List[10]; 
        for(int i = 0; i < spheres.length; i++) 
           spheres[i] = new ArrayList<BerylliumSphere>(); 
    } 
}
Run Code Online (Sandbox Code Playgroud)

一旦你有一个List []的引用,你可以看到你得到一些编译时检查.问题是数组是协变的,因此List []也是一个Object [],您可以使用它将ArrayList分配给您的数组,在编译时或运行时都没有错误.

但是,如果您知道自己不会进行上传并且需求相对简单,则可以创建一个泛型数组,它将提供基本的编译时类型检查.但是,通用容器实际上总是比一系列泛型更好的选择.

  • 你能解释一下吗?我理解擦除但不是在这种情况下. (5认同)

Vla*_*mir 13

问题1:

基本上,这是Java语言禁止的.这适用于Java语言规范中的泛型.

当你使用

ArrayList<Integer>[] pl2 = new ArrayList[10];    // warning
Run Code Online (Sandbox Code Playgroud)

你得到编译器警告,因为下面的例子将编译(为每行代码生成警告):

ArrayList wrongRawArrayList = new ArrayList();      // warning
wrongRawArrayList.add("string1");                   // warning 
wrongRawArrayList.add("string2");                   // warning  

pl2[0] = wrongRawArrayList;                         // warning 
Run Code Online (Sandbox Code Playgroud)

但是现在你应该包含ArrayList的数组Integer包含完全错误ArrayListString对象.

问题2:

正如已经回答的那样,声明p12为您提供了编译时间检查,并使您在从您的项目中获取项目时不会使用强制转换ArrayList.

略微修改前面的例子:

ArrayList<Integer>[] pl2 = new ArrayList[10];                // warning 

ArrayList<String> wrongArrayList = new ArrayList<String>();  // OK!
wrongArrayList.add("string1");                               // OK! 
wrongArrayList.add("string2");                               // OK!

pl2[0] = wrongArrayList;                                     // ERROR
Run Code Online (Sandbox Code Playgroud)

现在,由于您使用的是泛型,因此无法编译.但如果你使用

ArrayList[] pl2 = new ArrayList[10]; 
Run Code Online (Sandbox Code Playgroud)

您将获得与第一个示例中相同的结果.