最近在用Java写某个程序时希望写出一个包括ArrayList<xx>的数组
自己定义如下:
ArrayList<edge>[] edges = new ArrayList<edge>()[10];
然后编译器报错如下:
Cannot create a generic array of ArrayList<edge>;
在C++里可以这样比较方便的定义: vector<edge> a[100];
在Java里报错,查询了一下,见已经有人在stackoverflow上问了这个问题,链接如下:
http://stackoverflow.com/questions/4549192/create-an-array-of-arrayliststring-elements
上面的链接讲的多是解决(代替)方法,具体这样设计的原因还要自己继续深究。
一、出现这个问题的原因
正如IDE报错的信息所述:无法创建范型数组,底层的数组类型只能是Object的。
类型擦除:
简单来说,就是JVM将泛型存储的东西都视为Object,
即ArrayList<Integer>.class = ArrayList<String>.class = ArrayList<Object>.class
所以你如果定义了泛型数组,在使用的时候就很可能发生"猫插入狗列表"的事件
那我们接着探讨,为什么会引入类型擦除,<<Thinking in Java>>中介绍了这其中的历史原因,因为在JavaSE1.5之前是没有泛型的,
于是为了与之前版本类库的融合(不重写之前的类库),所以目前采用了类型擦除这种方法.
二、解决的方法
1、很简单,不用泛型。再额外定义一个class T, T里面包括一个ArrayList成员变量,借由T的public方法add向ArrayList里添加元素
2、方法一是对我这个程序的解决方法,对于Java泛型更通用的方法,class XX <T> { } 来说,
<<Thinking In Java>>上面讲了四种解决方案,具体如下:
http://blog.csdn.net/eric_sunah/article/details/7262486
没有任何方式可以推翻底层的数组类型,它只能是Object[]
所以作者讲的前三种方式涉及Object与其它类型之间的转型都可能会抛出异常或无法编译
所以应该采用上面链接所描述的第四种方法,将类型标记<T>传递到构造器中,以便从擦除中恢复