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

创建数组以在Java中存储泛型类型,java,generics,Java,Generics,假设我必须创建一个存储整数数组列表的数组,数组大小为10 下面的代码将执行此操作: ArrayList<Integer>[] pl2 = new ArrayList[10]; ArrayList[]pl2=新的ArrayList[10]; 问题1: 在我看来,更合适的代码应该是 ArrayList<Integer>[] pl2 = new ArrayList<Integer>[10]; ArrayList[]pl2=新的ArrayList[10

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

下面的代码将执行此操作:

ArrayList<Integer>[] pl2 = new ArrayList[10]; 
ArrayList[]pl2=新的ArrayList[10];

问题1:

在我看来,更合适的代码应该是

ArrayList<Integer>[] pl2 = new ArrayList<Integer>[10];    
ArrayList[]pl2=新的ArrayList[10];
为什么这不起作用

问题2:

下面两个例子都可以编译

  • ArrayList[]pl2=新的ArrayList[10]
  • ArrayList[]pl3=新的ArrayList[10]

  • pl2
    pl3
    的引用声明而言,有什么区别?

    泛型问题默认情况下由编译器发出警告

    编译后,由于类型擦除,它们都变成
    ArrayList[]pl2=new ArrayList[10]
    ,但编译器警告您这不好


    泛型已经添加到Java中,为了向后兼容,您可以将泛型与非泛型互换使用。

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

    引自Think in Java:

    不能创建数组的说法并不完全正确 泛型类型。则编译器不允许您实例化数组 属于泛型的。但是,它将允许您创建对的引用 这样的阵列。例如:

    List<String>[] ls; 
    
    List[]ls;
    
    这会毫无怨言地通过编译器。尽管你 无法创建包含泛型的实际数组对象,可以 创建非泛型类型的数组并强制转换它:

    //: 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>(); 
        } 
    }
    
    /:arrays/ArrayOfGenerics.java
    //可以创建泛型数组。
    导入java.util.*;
    公共类ArrayOfGenerics{
    @抑制警告(“未选中”)
    公共静态void main(字符串[]args){
    列表[]ls;
    列表[]la=新列表[10];
    ls=(列表[])la;/“未选中”警告
    ls[0]=新的ArrayList();
    //编译时检查产生错误:
    //!ls[1]=新的ArrayList();
    //问题:列表是对象的子类型
    Object[]objects=ls;//因此分配是确定的
    //编译并运行,无需投诉:
    对象[1]=新的ArrayList();
    //然而,如果你的需求是直截了当的,那就是
    //可以创建泛型数组,尽管
    //带有“未选中”警告:
    列表[]球体=
    (列表[])新列表[10];
    对于(int i=0;i
    一旦对列表[]进行了引用,就可以看到 获取一些编译时检查。问题是数组是 协变,因此列表[]也是对象[],您可以使用 此选项用于将ArrayList分配到数组中,此时不会出现错误 编译时或运行时

    如果你知道你不会 向上投射和您的需求相对简单,但是,这是可能的 创建一个泛型数组,它将提供基本的编译时间 类型检查。但是,通用容器实际上总是一个 比泛型数组更好的选择

    但是

    ArrayList[]pl2=新的ArrayList[10];
    pl2.put(新整数(10));
    整数i=p12.get(0);//这是真的,不需要铸造
    
    数组是协变的。这意味着它们在运行时保留其元素的类型。Java的泛型不是。他们使用类型擦除基本上掩盖了正在进行的隐式转换。理解这一点很重要

    你需要使用

    此外,数组还携带有关其属性的运行时类型信息 组件类型,即关于所包含元素的类型。 在以下情况下使用有关组件类型的运行时类型信息: 元素存储在数组中,以确保没有“外来元素” 可以插入元素


    有关更多详细信息,请查看问题1:

    基本上,这是Java语言所禁止的。这是一本书

    当你使用

    ArrayList<Integer>[] pl2 = new ArrayList[10];    // warning
    
    但是现在您的数组,应该包含
    Integer
    ArrayList
    ,包含了
    String
    对象的
    ArrayList
    完全错误

    问题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
    
    您将得到与第一个示例相同的结果。

    问题1 不能创建参数化类型的数组

    问题2
    这意味着arraylist可以存储任何对象类型,如字符串、整数、自定义对象等。

    让我们先从问题2开始,然后回到问题1:

    问题2:

    > ArrayList[]pl2=新的ArrayList[10]; ArrayList[]pl3=新的ArrayList[10]

    p12的引用声明和 p13是相关的吗

    在pl2中,确保了比p13更好的类型安全性

    如果我为pl2写作:

    pl2[0]=new ArrayList<String>();
    
    pl2[0]=newarraylist();
    
    它将给我一个编译器错误,说明“无法从
    ArrayList
    转换为
    ArrayList

    因此,它确保了编译时的安全性

    但是如果我为第13页写作

    pl3[0]=new ArrayList<String>();
    pl3[1]=new ArrayList<Integer>();
    
    pl3[0]=newarraylist();
    pl3[1]=新的ArrayList();
    
    它不会抛出任何错误,开发者有责任在从p13中提取数据时正确地编码和检查,以避免在运行时进行任何不安全的类型转换

    问题1:

    这可能就是泛型的工作方式。在主阵列初始化期间,
    ArrayList[]pl2=new ArrayList[10]
    ,lef
    ArrayList wrongRawArrayList = new ArrayList();      // warning
    wrongRawArrayList.add("string1");                   // warning 
    wrongRawArrayList.add("string2");                   // warning  
    
    pl2[0] = wrongRawArrayList;                         // warning 
    
    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
    
    ArrayList[] pl2 = new ArrayList[10]; 
    
     ArrayList<Integer>[] pl2 = new ArrayList[10];
    
     ArrayList[] pl3 = new ArrayList[10];
    
    pl2[0]=new ArrayList<String>();
    
    pl3[0]=new ArrayList<String>();
    pl3[1]=new ArrayList<Integer>();
    
    pl2[0]=new ArrayList<Integer>();
    
    ArrayList<Integer>[] pl2 = new ArrayList[10];
    ArrayList[] pl3 = new ArrayList[10];
    
    It refers to a non-generic class or interface type declaration.
    
    It is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1).
    
    It is a raw type (§4.8).
    
    It is a primitive type (§4.2).
    
    It is an array type (§10.1) whose element type is reifiable.
    
    It is a nested type where, for each type T separated by a ".", T itself is reifiable.
    
    For example, if a generic class X<T> has a generic member class Y<U>, then the type X<?>.Y<?> is reifiable because X<?> is reifiable and Y<?> is reifiable. The type X<?>.Y<Object> is not reifiable because Y<Object> is not reifiable.