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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Clare0621 中级黑马   /  2014-1-3 23:06  /  1595 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 Clare0621 于 2014-1-4 21:02 编辑

在张老师视频中看到关于通过反射绕过集合的泛型机制问题:
视频中,张老师定义了一个Integer类型的ArrayList,然后通过反射想集合中添加了一个字符串,并成功输出到控制台。
我自己定义了一个String类型的ArrayList,然后通过反射向其中添加了一个Integer元素,打印时就出现了类型转换异常,编译没问题。代码如下:
  1. public class GenericTest {
  2.         public static void main(String[] args) throws Exception {
  3.                 //通过反射可绕过泛型机制
  4.                 ArrayList<String> collection = new ArrayList<String>();
  5.                 collection.add("abc");
  6.                 collection.getClass().getMethod("add", Object.class).invoke(collection, 4);
  7.                 System.out.println(collection.get(1));
  8.         }
复制代码

谁能解释下什么原因?



评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

5 个回复

倒序浏览
PrintStream类中有println(Object x), println(String x),但是没有println(Integer x)
ArrayList<Integer> collection = lst;
执行的是println(Object x),先执行String.valueOf(x), 然后再用print(String)打印,所以不会出错。
ArrayList<String> collection = lst;  
执行的是println(String x)方法,Integer转String出错。
你把鼠标放在println上就能看到调用的是println(String x)方法方法。与反射和泛型没有关系

评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

回复 使用道具 举报
上次有人在帖子中分析过其中的原因。
问题就是泛型参数是String类型时,在往泛型集合中添加Integer,又用System.out.println()获取
该数据时,会要求强制转换为String类型,所以会报类型转换异常.
我就知道一个结论:
在通过反射的方式向泛型集合中加入不同类型的数据时:
所有泛型参数是8种基本数据类型的封装类都可以用System.out.println(collection.get(1))获取;
所有泛型参数是引用数据类型的都要用反射的方式来获取
即collections2.getClass().getMethod("get", int.class).invoke(collection, 1);

评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

回复 使用道具 举报
代码如下:

  1.     public static void main(String[] args) throws Exception {
  2.         //通过反射可绕过泛型机制
  3.         ArrayList<String> collection = new ArrayList<String>();
  4.         collection.add("abc");
  5.         collection.getClass().getMethod("add", Object.class).invoke(collection, 4);
  6.         /*这是ArrayList的get方法public E get(int index)
  7.          * 因为他返回一个泛型结果E,所以collection的get返回的是String类型,
  8.          * 而collection.get(1)实际得到的数据类型是Integer(add将int型封装为Integer类型),
  9.          * 类型不匹配,报告转化异常,不能将Integer转化为String类型,
  10.          *
  11.          * 下面这两种都会失败
  12.          * Integer i = collection.get(1);  //因为类型不可转化,所以编译不通过
  13.          * String  s = collection.get(1);   //编译器认为类型相同,编译通过,可运行就会失败
  14.          * 要想得到集合中的4这个值,就只用找Integer与String类型的父集,也就是Object类型,
  15.          * Object类型是String的父类,所以编译器不会报编译错误
  16.          * Object类型是Integer的父类,所以也不会报运行错误
  17.          * 搞定
  18.          * */
  19.         
  20.         Object o = collection.get(1);
  21.         System.out.println(o);
  22.     }
复制代码

希望你能采纳

评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

回复 使用道具 举报
哇哈哈,受教了
回复 使用道具 举报
额,明白了,谢谢诶楼上诸位。。。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马