有如下代码片段
1 ArrayList<String> collection2 = new ArrayList<String>();
2 collection2.add("abc");
3 collection2.getClass().getMethod("add", Object.class).invoke(collection2,
4 new Integer(48));
5 Object obj=collection2.get(1);
6 System.out.println(obj.getClass().getName());
7 // System.out.println(collection2.get(1).getClass().getName());第7行不注释掉时会出现ClassCastException,但是如果按照第5、6行这样写又可以顺利通过编译并正常显示java.lang.Integer
在此想请教各位java大神这样分开写和合着写的区别何在,以及为什么分开写就不会出现异常。
先谢谢各位大神,纠结了很久了,还是想不通Java泛型ArrayListString对象
1 ArrayList<String> collection2 = new ArrayList<String>();
2 collection2.add("abc");
3 collection2.getClass().getMethod("add", Object.class).invoke(collection2,
4 new Integer(48));
5 Object obj=collection2.get(1);
6 System.out.println(obj.getClass().getName());
7 // System.out.println(collection2.get(1).getClass().getName());第7行不注释掉时会出现ClassCastException,但是如果按照第5、6行这样写又可以顺利通过编译并正常显示java.lang.Integer
在此想请教各位java大神这样分开写和合着写的区别何在,以及为什么分开写就不会出现异常。
先谢谢各位大神,纠结了很久了,还是想不通Java泛型ArrayListString对象
解决方案 »
- 定时任务 持久化
- java高手帮帮忙,小弟拜谢
- jar文件如何双击运行?
- JAVA对数字证书的常用操作(转载)
- jvm 内存溢出的几个问题,请各位指教,谢谢!!!
- 求教一个有关windows接口的问题
- 请高手指点,我要是弄懂,送200分!
- JFrame窗体怎么一开始就让它最大化?
- 有关线程的两个问题很简单,isInterrupt()和yield()
- 有关javamail的问题,异常no object DCH for MIME type multipart/mixed
- String 数组问题
- 求高手解释一下有关与父类与子类构造器及变量出示化时间点的问题,本人执行了这段程序,顿感价值观都颠覆了呀!!!!
Object obj=collection2.get(1);向上转型成Object啦
collection2.get(1).getClass().getName()而这个你没有向上转型,而且你泛型声明的是String,但是放的是Integer,所以类型转换错啦!
System.out.println(Class(? extends String)collection2.get(1).getClass().getName());
猜测是这样,字节码里其实会对collection2.get(1)进行一次cast 113: getstatic #68; //Field java/lang/System.out:Ljava/io/PrintStream;
116: aload_1
117: iconst_1
118: invokevirtual #64; //Method java/util/ArrayList.get:(I)Ljava/lang/Object;
121: checkcast #84; //class java/lang/String
124: invokevirtual #25; //Method java/lang/Object.getClass:()Ljava/lang/Class;
127: invokevirtual #86; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
collection2.add("abc");
collection2.getClass().getMethod("add", Object.class).invoke(collection2,new Integer(48));
Object obj=collection2.get(1);
// System.out.println(obj.getClass().getName());
System.out.println(collection2.get(1).getClass().getName());
试了一下,在没有手动 cast 的情况下,指定了具体类型的泛型返回值调用任何方法都会导致编译结果中存在其指定的具体类型的cast。即使你调用的方法是任何 Object 都有的 hashCode() 或 getClass()就是说,泛型擦除时有两种情况不会自动添加指定类型的 cast:1 - 存在手动cast代码: ((Object)collection2.get(1)).hashCode();
2 - 返回结果直接赋值给更宽泛的类型的 reference: Object o = collection2.get(1);对于2,应该还是存在自动添加的 cast,只不过这个 cast 应该是根据要被赋值的变量的声明类型添加的:import java.util.ArrayList;
import java.util.List;public class CastTest { public static void main(String[] args) throws Exception { List<Integer> list = new ArrayList<Integer>();
list.add(2);
list.getClass().getMethod("add", Object.class).invoke(list, Double.valueOf(48.0));
System.out.println(((Number)list.get(1)).hashCode()); // compile and run with no problem.
// System.out.println(list.get(1).hashCode()); // java.lang.ClassCastException
Number n = list.get(1); // compile and run with no problem.
System.out.println(n.getClass());
}
}
因此此处collection2.get(1)得到的是一个String类型的引用,就相当于String str = collection2.get(1);但是此处这个引用指向的却是Integer类型实例。(- -!都是反射搞出来的)。
所以collection2.get(1).getClass()就要ClassCastException了
6.7行代码 你先向上转成object类型了,所以没问题。
那么我在进行Object obj=collection2.get(1);的时候为什么没有cast,真心求解
那么我在进行Object obj=collection2.get(1);的时候为什么没有cast,真心求解你的line 5 做了一次强转,其实可以写成这样
String str = collection2.get(1);
Object obj = str;collection2.get(1)返回的是一个泛型指定的String类型变量,
Object obj = collection2.get(1);
就是把String类型向上强转为Object类型,Integer是Obj的子类,所以obj.getClass()就没有类型歧义了。如果是collection2.get(1).getClass(),就相当于
String str = collection2.get(1);
str.getClass();
这里的str指向的是Integer类型实例,而String和Integer类型没有继承关系,所以str.getClass()就报错