使用反射为泛型集合添加其他类型的数据时遇到的问题

泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合进会去掉“类型”信息,使程序运行效率不受影响。

由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合虽加入其它类型的数据。
所以我们可以用反射为泛型集合添加其他类型的数据。
 
例1:
ArrayList<Integer> arrayList = new ArrayList<Integer>();
  arrayList .add(10);
  arrayList .add(20);
  arrayList .getClass().getMethod("add",Object.class).invoke(arrayList ,"hbase");
  System.out.println(arrayList .get(2));//虽然索引为2的位置存的是String类型,但编译时编译器会认为arrayList .get(2)返回的时是Integer类型,但在运行取值时取的仍是                                         //String类型

 

输出:hbase

 

 
例2:
ArrayList<String> arrayList = new ArrayList<String>();
  arrayList1.add("hadopp");
  arrayList1.add("hive");
  arrayList1.getClass().getMethod("add",Object.class).invoke(arrayList1,25);
  System.out.println(arrayList1.get(2));//虽然索引为2的位置存的是Integer类型,但编译时编译器会认为arrayList .get(2)返回的时是String类型,但在运行取值时取的仍                                       //Integer类型

报错!!
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
 at com.mobin.generic.GenericTest.main(GenericTest.java:20)

 

报错代码:System.out.println(arrayList1.get(2));
Integer不能转成String,但例1为会又不报ClassCastException异常呢?(大家也可以先想想原因是什么再看下面的分析)
 
 
 
下面分析下原因:
出现ClassCastException这个异常可以断定的是类型的转换错误。
原因就在Syststem.out.println这条语句,
上图是println()的所有重载方法,除了bool,char,char[],double,float,int,String,long类型外,当传入的参数是其他类型时被会被当作是Object从而调用println(Object)方法。
在例1中由于arrayList1.get(2)返回的是Integer所以调用的是println(Object)方法,验证:把鼠标放到println方法上即可.
好,我们再进入println(Object x)的源码去看看
参数都被自动的转成了String类型!!!
相当于Object x = arrayList.get(2);   //所有对象都属于Object
         String s = String.valueOf(x);
所以不会报错。
 
 
再看第二段代码的println调用的是println(String x);
同样进入源码去看看:
相当于String x = arrayList.get(2);      //这里运行时arrayList.get(2)所得的值的类型是Integer,又相当于String x = Integer;所以才报错
 
posted @ 2015-08-31 17:28  MOBIN  阅读(2859)  评论(0编辑  收藏  举报