现在的位置: 首页 > 综合 > 正文

cannot create a generic array

2013年02月26日 ⁄ 综合 ⁄ 共 1668字 ⁄ 字号 评论关闭

public class test<E> {
 public E[] r;
 public test() {
  r = ne w E[3];
 }

#1楼 得分:0回复于:2010-09-03 20:10:58没有泛型数组
#2楼 得分:0回复于:2010-09-03 20:40:11Java的泛型在编译时会擦除类型信息。Java中的数组是通过反射动态建立的。没有了类型信息怎么能构造出数组。
#3楼 得分:0回复于:2010-09-03 20:59:04java是不支持泛型数组的。
其实List或ArrayList就是已经做好了的泛型数组。
#4楼 得分:0回复于:2010-09-03 21:06:03其实这个可以参考ArrayList。
ArrayList虽然也是范型类,但是里面也是用Object数组:Object[] elementData;
只是在get(int)的时候强转型(E)elementData[index];

如果直接用E[] elementData;也行。可以这样来初始化:Java code

1
<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->E[]elementData =(E[])new Object[N];

在Java中,Object[]数组可以是任何数组的父类,或者说,任何一个数组都可以向上转型成它在定义时指定元素类型为其父类的数组,这个时候如果我们往里面放不同于原始数据类型,但是满足有相同父类的数据时,编译不会有问题,但是在运行时会检查加入数组的对象的类型,于是会抛ArrayStoreException:

 

String[] strArray = new String[20];

Object[] objArray = strArray;

objArray[0] = new Integer(1); // throws ArrayStoreException at runtime

 

因为Java的范型会在编译后将类型信息抹掉,这样如果Java允许我们使用类似

 

Map[] mapArray = new Map[20];//Cannot createa generic array of Map

 

这样的语句的话,我们在随后的代码中可以把它转型为Object[]然后往里面放Map实例。这样做不但编译器不能发现类型错误,就连运行时的数组存储检查对它也无能为力,它能看到的是我们往里面放Map的对象,我们定义的在这个时候已经被抹掉了,于是而对它而言,只要是Map,都是合法的。想想看,我们本来定义的是装Map的数组,结果我们却可以往里面放任何Map,接下来如果有代码试图按原有的定义去取值,后果是什么不言自明。所以,Java编译器不允许我们new范型数组。

     List[] lsa = new List[10]; //Not
really allowed.

     Object[] oa = (Object[]) lsa;
     List li = new ArrayList();
     li.add(new Integer(3));
     oa[1] = li; //Unsound,
but passes run time store check

     String s =

oa
[1].get(0); //Run-time
error:ClassCastException.//笔者认为这应该是oa变量,好多地方这写的是isa,我觉得不对

这种情况下,由于JVM泛型的擦除机制,在运行时JVM是不知道泛型信息的,所以可以给oa[1]赋上一个ArrayList而不会出现ArrayStoreException,但是在取出数据的时候却要做一次类型转换,所以就会出现ClassCastException,如果可以进行泛型数组的声明,上面说的这种情况在编译期将不会出现任何的警告和错误,只有在运行时才会出错。而对泛型数组的声明进行限制,对于这样的情况,可以在编译期提示代码有类型安全问题,比没有任何提示要强很多。

抱歉!评论已关闭.