Java不能创建泛型数组的解决方案

Java不能创建泛型数组的解决方案

问题提出:

在java中是”不能创建一个确切的泛型类型的数组”的。

也就是说下面的这个例子是不可以的:

List<String>[] ls = new ArrayList<String>[10];  

而使用通配符创建泛型数组是可以的,如下面这个例子:

List<?>[] ls = new ArrayList<?>[10];  

这样也是可以的:

List<String>[] ls = new ArrayList[10];

下面使用Sun的一篇文档的一个例子来说明这个问题:

List<String>[] lsa = new List<String>[10]; // Not really allowed.    
Object o = lsa;    
Object[] oa = (Object[]) o;    
List<Integer> li = new ArrayList<Integer>();    
li.add(new Integer(3));    
oa[1] = li; // Unsound, but passes run time store check    
String s = lsa[1].get(0); // Run-time error: ClassCastException.

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

而对泛型数组的声明进行限制,对于这样的情况,可以在编译期提示代码有类型安全问题,比没有任何提示要强很多。

解决方案

1. 通配符

通配符的解决方案甚至可以放Integer和String都可以!!!

The Java™ Tutorials: Generics给出的解决方案如下:

List<?>[] lsa = new List<?>[10];                //1
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
// Correct.
lsa[1] = li;
// Run time error, but cast is explicit.
Integer s = (Integer) lsa[1].get(0);              //2

借助于无限定通配符却可以,? 代表未知类型,所以它涉及的操作都基本上与类型无关,因此 jvm 不需要针对它对类型作判断,因此它能编译通过,但是,只提供了数组中的元素因为通配符原因,它只能读,不能写。比如,上面的 lsa 这个局部变量,它只能进行 get() 操作,不能进行 add() 操作。当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。但是可以通过li变量来进行add() 操作。

综上:数组的类型不可以是类型变量,除非是采用通配符的方式。因为对于通配符的方式,最后取出数据是要做显式的类型转换的。

2. 反射

反射的解决方案只能放置一开始声明的<>中的内容!!!

使用java.util.reflect.Array,可以不使用通配符,而达到泛型数组的效果:

   List<String>[] lsa = (List<String>[])Array.newInstance(ArrayList.class, 4);     //1
   Object o = lsa;
   Object[] oa = (Object[]) o;
   List<String> li = new ArrayList<String>();
   li.add("3");
   / Correct.
   oa[1] = li;
   // Run time error, but cast is explicit.
   String s = lsa[1].get(0);                                                       //2
   System.out.println(s);

可以看到,我们利用了Array.newInstance()生成了泛型数组,这里没有使用任何通配符,在第2处也没有做显式的类型转换,但是在第1处,仍然存在显式类型转换。

3.3 总结

要想使用泛型数组,要求程序员必须执行一次显示的类型转换,也就是将类型检查的问题从编译器交给了程序员。实际上Java的设计者正是此意,在(List<String>[])Array.newInstance(ArrayList.class, 4)处会有一个unchecked warning,正是编译器在提醒程序员:这个地方,我不会帮你做类型检查,你要自己小心!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值