A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

为什么红线的部分可以 下面的就类转换异常呢?

why.png (10.16 KB, 下载次数: 4)

why.png

3 个回复

倒序浏览
本帖最后由 a6511631 于 2014-8-4 09:40 编辑

这段代码通过反射跳过了编译器的检查,使得编译能够通过,但是在用ArrayList的get(index)方法时,定义泛型为<Integer>的数组集合在add()方法中用的是String类型的对象,可以正常输出;但是,用了泛型<String>的数组集合在add()方法中用的Integer却会报类型转换异常(被编译器抓到了)。而如果直接打印该ArrayList的话,又能够正常打印!
想必是get(index)方法源码中出现了问题。查了下源码。
源码如下:
  1. public E get(int index) {
  2.         rangeCheck(index);

  3.         return elementData(index);
  4.     }
复制代码
那个rangeCheck(index)方法是检查index索引是否越界的。
关键的的是这个elementData(index)。
它的方法如下:
  1.     E elementData(int index) {
  2.         return (E) elementData[index];
  3.     }
复制代码
发现是返回一个elementData[index]。就是返回一个叫elementData的数组的处于索引index位置的数组元素。在ArrayList类源码中定义了一个叫elementData的Object数组用于存放数据,它的定义格式是:    private transient Object[] elementData;
可以发现,在用ArrayList的get(index)方法时,定义泛型为<Integer>的数组集合在add()方法中用的是String类型的对象,可以正常输出(不会被编译器抓到);但是,用了泛型<String>的数组集合在add()方法中用的Integer却会报类型转换异常(被编译器抓住,没跳过编译)。
回复 使用道具 举报
试了下  如果打印al的话是可以的,但是用al.get(0)报错。。不知道咋回事
回复 使用道具 举报
对于红线部分:

System.out.println(al.get(0));      //打印abc

System.out.println(al.get(0).getClass());     //报错java.lang.String cannot be cast to java.lang.Integer


对于非红线部分:

System.out.println(al.get(0));     //报错java.lang.Integer cannot be cast to java.lang.String

Method getEle = al.getClass().getMethod("get", int.class);
System.out.println(getEle.invoke(al, 0));     //打印12

System.out.println((Object)al2.get(0));      //打印12


结论:
1,反射会绕过泛型检查。
2,(我猜是)get(0)方法在取得元素后会进行类型转换,但若我们对元素进行强制转换或者其他某些操作,会使get(0)跳过类型转换操作。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马