黑马程序员技术交流社区

标题: 利用反射调用泛型类型的问题 [打印本页]

作者: 林其荣    时间: 2013-1-13 18:11
标题: 利用反射调用泛型类型的问题
张孝祥老师讲的一个泛型的知识点时,碰到了一个问题,张老师说泛型只是给编译器看的,以张老师举的例子说明:
都是ArrayList类型的对象,一个是String型(ArrayList<String>)arr1,另一个是Integer型(ArrayList<Integer>)arr2,这两个对象在编译完成后生成的字节码是相同的,利用反射调用add方法时应该可以把泛型屏蔽的,但是我碰到了下面的问题,代码如下:
  1.   ArrayList<Integer> arr1 = new ArrayList<Integer>();
  2.          arr1.getClass().getMethod("add", Object.class).invoke(arr1, "abc");
  3.          System.out.println(arr1.get(0));
复制代码
上面这个没有问题,可以把泛型屏蔽掉,但是下面的却不行:
  1. ArrayList<String> arr2 = new ArrayList<String>();
  2.          arr2.getClass().getMethod("add", Object.class).invoke(arr2, 2);
  3.          System.out.println(arr2.get(0));
复制代码
运行报了异常:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
        at day1.GenericTest.main(GenericTest.java:34)


不知道为什么,String型的可以屏蔽,Integer的却不行

作者: 黄锦成    时间: 2013-1-13 18:49
这个问题我也问过,但是还没解决
作者: 林嘉健    时间: 2013-1-13 19:02
错误原因是由于你的System.out.println(arr2.get(0));

改成这样就正常OK了
ArrayList<String> arr2 = new ArrayList<String>();
              arr2.getClass().getMethod("add", Object.class).invoke(arr2, 2);
              System.out.println(String.valueOf(arr2.get(0)));
作者: Rancho_Gump    时间: 2013-1-13 19:13
正好看到这
作者: Rancho_Gump    时间: 2013-1-13 19:18
手机上的看不到代码  我估摸着可能和自动装拆箱有关吧
作者: jonn    时间: 2013-1-13 19:23
类的转换异常,包转型类型Integer 与 String 转换产生异常,解决方式:采用泛型上限与下限 转换就ok了
注意,第一个程序容器方的是Integer 所以没问题 而第二个程序容器放的是 String,System.out.println(arr2.get(0)) 打印的值是 Integer与容器String类型不符,
所以产生类转换异常错误,改成 Integer.toString(arr2.get[0])即可
ClassCastException 新手最容易犯着错误,自己注意下

作者: 王阳    时间: 2013-1-13 20:42
赵文 发表于 2013-1-13 19:23
类的转换异常,包转型类型Integer 与 String 转换产生异常,解决方式:采用泛型上限与下限 转换就ok了
注意 ...

感觉你的方法说不通。因为这样的话,那么怎么解释第一个呢? 可是在Integer里保存String类型。一样存在类型转换问题,个人认为不仅仅是类型转换的问题。
作者: jonn    时间: 2013-1-13 20:53


不是类转换异常么?

作者: jonn    时间: 2013-1-13 20:55
王阳 发表于 2013-1-13 20:42
感觉你的方法说不通。因为这样的话,那么怎么解释第一个呢? 可是在Integer里保存String类型。一样存在类 ...

间接利用反射调用泛型类型,但还是要依据容器数据类型一致,错误产生异常难道不是ClassCastException 类转换异常.....
作者: 王阳    时间: 2013-1-13 22:23
赵文 发表于 2013-1-13 20:55
间接利用反射调用泛型类型,但还是要依据容器数据类型一致,错误产生异常难道不是ClassCastException 类 ...

错误虽然是转换异常,但是我意思是,为什么前一个可以而后一个不可以呢。。。?这个才是问题。因为一旦运行起来泛型就被擦除了的。。为什么还会有类型转换异常,这个就是我想问的
作者: 黑马刘向阳    时间: 2013-1-13 22:37
看了下源码,println(x) 如果x是String,则是直接打印x,如果x是其他类型,则打印String.valueOf(x),
因为arr2被添加了String泛型,所以编译时就会认为x是String类型,不会再使用调用String.valueOf(x)的那个println(x)方法,
但是运行时取出的是Integer,所以出现类型转换异常
作者: 鲁中需    时间: 2013-1-13 22:57
楼上正解,你把最后一个输出语句换成:
System.out.println(String.valueOf(arr2.get(0)));
或者:
for(Iterator it = arr2.iterator(); it.hasNext();){
                                System.out.println(it.next());
                        }
就没问题了,关键就是这个方法println()内部工作机制。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2