黑马程序员技术交流社区
标题:
为什么红线的部分可以 下面的就类转换异常呢?
[打印本页]
作者:
alive
时间:
2014-8-4 01:06
标题:
为什么红线的部分可以 下面的就类转换异常呢?
为什么红线的部分可以 下面的就类转换异常呢?
why.png
(10.16 KB, 下载次数: 26)
下载附件
2014-8-4 01:05 上传
作者:
a6511631
时间:
2014-8-4 08:45
本帖最后由 a6511631 于 2014-8-4 09:40 编辑
这段代码通过反射跳过了编译器的检查,使得编译能够通过,但是在用ArrayList的get(index)方法时,定义泛型为<Integer>的数组集合在add()方法中用的是String类型的对象,可以正常输出;但是,用了泛型<String>的数组集合在add()方法中用的Integer却会报类型转换异常(被编译器抓到了)。而如果直接打印该ArrayList的话,又能够正常打印!
想必是get(index)方法源码中出现了问题。查了下源码。
源码如下:
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
复制代码
那个rangeCheck(index)方法是检查index索引是否越界的。
关键的的是这个elementData(index)。
它的方法如下:
E elementData(int index) {
return (E) elementData[index];
}
复制代码
发现是返回一个elementData[index]。就是返回一个叫elementData的数组的处于索引index位置的数组元素。在ArrayList类源码中定义了一个叫elementData的Object数组用于存放数据,它的定义格式是: private transient Object[] elementData;
可以发现,在用ArrayList的get(index)方法时,定义泛型为<Integer>的数组集合在add()方法中用的是String类型的对象,可以正常输出(不会被编译器抓到);但是,用了泛型<String>的数组集合在add()方法中用的Integer却会报类型转换异常(被编译器抓住,没跳过编译)。
作者:
阿磊
时间:
2014-8-4 08:47
试了下 如果打印al的话是可以的,但是用al.get(0)报错。。不知道咋回事
作者:
m313786372
时间:
2014-8-4 09:53
对于红线部分:
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)跳过类型转换操作。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2