cannot create a generic array

本文深入分析了Java中泛型数组的原理、局限性以及如何通过使用预定义的泛型集合类(如List或ArrayList)来实现类似功能。详细解释了Java编译器为何不允许直接创建泛型数组,以及如何规避这一限制,同时讨论了数组向上转型的机制及其潜在风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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,如果可以进行泛型数组的声明,上面说的这种情况在编译期将不会出现任何的警告和错误,只有在运行时才会出错。而对泛型数组的声明进行限制,对于这样的情况,可以在编译期提示代码有类型安全问题,比没有任何提示要强很多。


<think>好的,用户的问题是关于Java泛型中数组类型的限制。他提到泛型不能是数组类型,但里面的参数可以是数组类型。我需要详细解释这一点。 首先,我应该回忆Java泛型的基本规则。Java不允许创建泛型数组,比如不能有`List<String>[]`这样的类型。这是因为数组在运行时需要知道其元素的确切类型,而泛型由于类型擦除,无法在运行时提供这个信息,导致类型不安全。 然后,用户提到泛型参数可以是数组类型。例如,`List<String[]>`是允许的。这里,泛型参数是`String[]`,但整个列表本身并不是数组类型,而是泛型类。这种情况下,类型擦除不影响,因为泛型参数在编译时会被检查,而数组作为参数时,其类型信息在运行时仍然存在。 接下来,我需要给出示例代码来说明这两种情况。比如,尝试创建泛型数组会导致编译错误,而使用数组作为泛型参数则是合法的。同时,要解释为什么第一种情况不允许,而第二种允许。 最后,按照用户的要求,提出相关问题。这些问题应该围绕泛型的限制、通配符、类型擦除以及如何安全地处理泛型数组展开。 总结回答结构:先回答问题,解释原因,给出代码示例,然后列出相关问题。</think><< 在Java中,泛型不能直接声明为数组类型(例如`MyClass<T[]>[]`),但泛型参数内部可以使用数组类型(例如`MyClass<String[]>`)。这是因为Java的类型擦除和数组的类型安全机制导致的。 **原因分析**: 1. **数组的类型安全**:Java数组在运行时必须明确知道元素的具体类型(称为"reified"类型),会强制检查插入元素的类型匹配性。 2. **泛型类型擦除**:泛型在编译后会被擦除为`Object`类型(或边界类型),运行时无法获取泛型的具体类型信息。 3. **类型不安全的可能性**:如果允许泛型数组,可能存在以下问题: ```java List<String>[] stringLists = new List<String>[1]; // 假设允许 List<Integer> intList = Arrays.asList(42); Object[] objects = stringLists; objects[0] = intList; // 绕过泛型类型检查 String s = stringLists[0].get(0); // 运行时抛出ClassCastException ``` **允许数组作为泛型参数**: ```java // 合法:泛型参数可以是数组类型 List<String[]> listOfArrays = new ArrayList<>(); listOfArrays.add(new String[]{"a", "b"}); // 合法:类定义中使用数组类型作为泛型参数 class ArrayHolder<T[]> { // 实际应定义为class ArrayHolder<T> T[] array; // 但字段可以是T[] } ``` **不允许泛型数组的示例**: ```java // 编译错误:Cannot create a generic array of List<String> List<String>[] arrayOfLists = new List<String>[10]; ``` **解决方法**: 1. 使用`ArrayList`等集合代替数组: ```java List<List<String>> listOfLists = new ArrayList<>(); ``` 2. 使用通配符类型: ```java List<?>[] arrayOfLists = new List<?>[10]; ``` 3. 通过反射创建(不推荐): ```java List<String>[] array = (List<String>[]) new List<?>[10]; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值