在写软构实验的时候,写出了这样的代码,然后报错:Generic array creation
诶,java中不允许创建泛型数组吗?为什么呢?
查找了一些资料,明白了,这是由于java对泛型的类型擦除特性导致的。
首先我们要搞清楚,java为什么要引入泛型?
先来看这样一段代码:
public static void main(String[] args) { List lists = new ArrayList(); lists.add("test"); lists.add(5); String s = (String)lists.get(0); System.out.println(s.length()); String s2 = (String)lists.get(1); System.out.println(s2.length()); }
这段代码先输出4,然后抛出java.lang.ClassCastException,提示Integer无法转换为String
原因就是list里面由于没有限定类型,所以元素之间的类型不同,不能统一处理。
而泛型的引入解决了这一问题。泛型提供了一种对所有类型都适用的处理方式,同时还限制了元素类型必须为指定类型,对元素进行类型检查。也就是说,泛型的引入是为了“统一”
看看加了泛型之后的情况:
直接在编译阶段报错了。
这就给出了泛型的一个原则:如果一段代码在编译时没有提出“未经检查的转换”警告,则程序在运行时不会引发ClassCastException异常。编程有一个原则:出错越早越好。所以,在编译阶段出错更容易定位和修复问题。
那么回到我们的中心问题:为什么不能创建泛型数组呢?
我们看一下这一段代码:
1) List<Integer> arrayOfIdList[] = new ArrayList<Integer>[10];// Suppose generic array creation is legal. 2) List<String> nameList = new ArrayList<String>(); 3) Object objArray[] = arrayOfIdList; // that is allowed because arrays are covariant 4) objArray[0] = nameList; 5) Integer id = objArray[0].get(0);
假设我们允许泛型数组的创建,java允许用父类型的引用来接收子类型对象,所以我们可以构造一个Object[]数组来接收泛型数组arrayOfIdList,这样,我们通过Object[]类型的引用来添加元素就不会受到泛型的限制,这就违背了泛型的原则。
那动态检查呢?这就涉及到java对泛型的类型擦除的特性。在运行时,泛型限制会被去掉,这里的ArrayList<Integer>会被视为ArrayList,所以在运行过程中也不会出现问题,可以正常赋值。
这就造成了arrayOfIdList中含有ArrayList<String>类的元素。
本质上,泛型就是在静态类型检查时起作用。而创建泛型数组会导致可以绕过泛型的限制,通过静态检查。所以java不允许创建泛型数组
参考:Why is Generic Array Creation not Allowed in Java? | TO THE NEW Blog
文章评论