创建数组以在Java中存储泛型类型
假设我必须创建一个存储整数数组列表的数组,数组大小为10 下面的代码将执行此操作:创建数组以在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
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.