黑马程序员技术交流社区

标题: 关于泛型和反射的一个问题 [打印本页]

作者: jaijaiok    时间: 2013-12-9 22:40
标题: 关于泛型和反射的一个问题
有如下代码片段
  1. 1  ArrayList<String> collection2 = new ArrayList<String>();
  2. 2   collection2.add("abc");
  3. 3   collection2.getClass().getMethod("add", Object.class).invoke(collection2,  
  4. 4                                                                   new  Integer(48));
  5. 5   Object obj=collection2.get(1);
  6. 6   System.out.println(obj.getClass().getName());
  7. 7 // System.out.println(collection2.get(1).getClass().getName());
复制代码
第7行不注释掉时会出现ClassCastException,但是如果按照第5、6行这样写又可以顺利通过编译并正常显示java.lang.Integer
在此想请教各位java大神这样分开写和合着写的区别何在,以及为什么分开写就不会出现异常。
先谢谢各位大神,纠结了很久了,还是想不通

作者: 衣带赞    时间: 2013-12-10 01:28
这个问题我之前也问过,不过没人能回答出来。不过可以肯定的是,只有在String类中才会出现这个问题,当你把泛型定义为Integer时,就没有问题了。为了验证,我还自己创建了一个Person类扔到泛型里面去,也不会出现这个异常。
据我估计,这是String类中一个很特别的地方。这个问题在编译时是没问题的,在运行时发生异常。那么就是在打印这个地方出了问题。我估计在打印一个被编译器认定为了String类的时候,会检测它是否为String类,如不是,发生异常。当打印一个不是String类的其它类时,调用被打印类的toString()方法。只有这样才能解释为什么此处会发生异常。我例子的代码:
  1. import java.util.ArrayList;

  2. public class Test3 {

  3.         public static void main(String[] args) throws Exception{
  4.                  
  5.         //泛型限定为Integer,加入String类,无异常
  6.         ArrayList<Integer> al1 = new ArrayList<Integer>();
  7.         al1.add(123);               
  8.         al1.getClass().getMethod("add", Object.class).invoke(al1, "gg");
  9.         System.out.println(al1.get(1));

  10.                 //泛型限定为Person,加入String类,无异常
  11.                 ArrayList<Person> al3 = new ArrayList<Person>();
  12.                 al3.add(new Person());
  13.                 al3.getClass().getMethod("add",Object.class).invoke(al3,"来个String试试");
  14.                 System.out.println(al3.get(1));

  15.                 //泛型限定为String,加入Integer类,出现java.lang.ClassCastException
  16.         ArrayList<String> al2 = new ArrayList<String>();
  17.             al2.add("abc");
  18.         al2.getClass().getMethod("add", Object.class).invoke(al2,123);                 
  19.             System.out.println(al2.get(1));               
  20.         }
  21. }

  22. class Person
  23. {
  24.         public String toString(){
  25.                 return "自己创建一个类试试看";
  26.         }
  27. }
复制代码
所以,你那个代码只要改一个地方就可以了
System.out.println(collection2.get(1).getClass().getName()); 改为
System.out.println(((Object)collection2.get(1)).getClass().getName()); 即可









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