java不支持泛型数组_JAVA泛型中的类型擦除及为什么不支持泛型数组

一,数组的协变性(covariant array type)及集合的非协变性

设有Circle类和Square类继承自Shape类。

关于数组的协变性,看代码:

public static doubletotalArea(Shape[] arr){double total = 0;for(Shape shape : arr) {if(shape != null)

total+=shape.area();

}returntotal;

}

如果给 totalArray(Shape[] arr) 传递一个Circle[] 类型的数组,这是可以的,编译通过,也能正常运行。也就是说:Circle[] IS-A Shape[]

关于集合的协变性,看代码:

public static double totalArea(Collectionarr){double total = 0;for(Shape shape : arr) {if(shape != null)

total+=shape.area();

}returntotal;

}

如果给totalArea(Collectionarr)传递一个 Collection类型的集合,这是不可以的。编译器就会报如下的错误:

The method totalArea(Collection) in the type Demo is not applicable for the arguments (Collection)

也就是说:Collection IS-NOT-A Collection

二,如果解决集合的非协变性带来的不灵活?

出现了泛型!

public static double totalArea(Collection extends Shape>arr){double total = 0;for(Shape shape : arr) {if(shape != null)

total+=shape.area();

}returntotal;

}

这样,就可以给totalArea(Collection extends Shape>arr)

传递Collection、Collection、Collection类型的参数了。

三,泛型的类型擦除及类型擦除带来的ClassCastException异常

JAVA的泛型只存在于编译层,到了运行时,是看不到泛型的。

还是拿数组来做对比:

1 String[] str = new String[10];2 Object[] obj =str;//向上转型3

4 //Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer

5 obj[0] = new Integer(2);

第5行代码在运行时会抛第4行中表示的异常。

再来看泛型:

1 ArrayList intList = new ArrayList();2 intList.add(2);3 Object obj =intList;4

5 //Type safety: Unchecked cast from Object to ArrayList

6 ArrayList strList = (ArrayList)obj;7

8 //Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

9 String str = strList.get(0);10 str.trim();//do something with str

编译器会对第6行提示第5行所示的警告。程序运行到第9行时抛出ClassCastException异常。因为ArrayList存储的本质上是一个Integer。

现在分析下第6行代码:

obj是Object类型的引用,strList是一个ArrayList类型的引用,因此,向下转型时编译器给出了警告,在运行时,由于类型擦除,相当于

ArrayList strList = (ArrayList)obj;

因此,代码运行到第6行也能通过。

对于第9行代码:

strList是一个ArrayList类型的引用,当然可以调用 ArrayList的get方法。因此,编译时没问题。但在运行时,

由于,String str = strList.get(0);会编译成String str = (String)strList.get(0);

而strList.get(0)得到 的是一个Integer对象,然后把它赋值给 String str,由于Integer IS-NOT-A String。故抛出ClassCastException。

四,为什么不支持泛型数组

参考下面代码:

1 //Cannot create a generic array of ArrayList

2 ArrayList[] intArr = new ArrayList[10];3 Object[] obj =intArr;4

5 ArrayList listStr = new ArrayList();6 obj[0] =listStr;7

8 ArrayList listInt = intArr[0];9 Integer i = listInt.get(0);//想要Integer,但却是String

假设允许泛型数组,那么第2行是正确的,那么将不会有第1行中所示的编译错误。

那么就可以将 intArr 转型成 Object[],然后向Object[]放 ArrayList,而不是我们想要的ArrayList

因此,在运行时,类型是擦除的,运行时系统无法对数组中存储的类型做检查。它看到仅是:向intArr数组里面放 ArrayList对象。

相当于:

//ArrayList listStr = new ArrayList();

ArrayList listStr = newArrayList();//运行时看到的情况//ArrayList listInt = intArr[0];

ArrayList listInt = intArr[0];//运行时看到的情况

在上面第9行,如果改成:

Object o = listInt.get(0);//do something with o

我们以为Object o 它实际引用 的是Integer类型的,但它底层却是String类型的,如果调用 hashCode(),我们以为它执行的是Integer的hashCode(),但它执行的是String的hashCode(),那意味着发现不了错误。。。。。。。

因此,JAVA不支持泛型数组。

参考:

http://www.blogjava.net/deepnighttwo/articles/298426.html

http://www.blogjava.net/sean/archive/2005/08/09/9630.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值