黑马程序员技术交流社区

标题: 关于泛型的问题 [打印本页]

作者: 谢波    时间: 2013-3-26 06:40
标题: 关于泛型的问题
本帖最后由 谢波 于 2013-3-26 21:01 编辑
  1. import java.util.*;

  2. public class GenericTest {

  3.         public static void main(String[] args) throws Exception{
  4.                 ArrayList<String> a1 = new ArrayList<String>();
  5.                 a1.add("abc");
  6.                 ArrayList<Integer> a2 = new ArrayList<Integer>();
  7.                 a2.add(3);
  8.                
  9.                 System.out.println(a1.getClass() == a2.getClass());
  10.                                 
  11.                 //通过反射就可以将Integer添加到a1中
  12.                 a1.getClass().getMethod("add", Object.class).invoke(a1, 5);
  13.                 System.out.println(a1.get(1));
  14.         }
  15. }
复制代码
话说,泛型不是用在编译期吗,而且看张老师的视频里这样写没问题
但是自己写了下最后一句,a1.get(1)编译的时候没问题
运行的时候,就出现了类型转换异常
求解,谢谢{:3_57:}
作者: 胡志超    时间: 2013-3-26 08:21
你的报错信息呢???怎么说的
作者: 小黑黑    时间: 2013-3-26 08:59

我帮你把报错的信息贴出来了,这里说类型转化的异常。
我个人觉得,你没有注意到一点:张老师说只要能跳过编译器,就可以往某个反省集合中加入其它类型的数据,如用反射得到集合,在调用add方法即可。
此时,你并没有跳过编译器,虽然编译时通过了,但是在编译时,已经确定了a1中只能存String类型的了,所以运行时,会报告错误。我觉得重点是如何跳过编译器。

作者: 谢波    时间: 2013-3-26 09:04
小黑黑 发表于 2013-3-26 08:59
我帮你把报错的信息贴出来了,这里说类型转化的异常。
我个人觉得,你没有注意到一点:张老师说只要能跳过 ...

上一行反射代码不就是跳过编译器的吗?跟张老师的有什么区别吗?
作者: 胡发友    时间: 2013-3-26 09:56
System.out.println(a1.get(1)); 这里调用的是al String类型的方法,不是反射回来的方法
作者: 小黑黑    时间: 2013-3-26 10:00
谢波 发表于 2013-3-26 09:04
上一行反射代码不就是跳过编译器的吗?跟张老师的有什么区别吗?
  1. import java.lang.reflect.InvocationTargetException;
  2. import java.util.ArrayList;
  3. import java.util.Collection;

  4.         public class RefectColl {
  5.             public static void main(String[] args) throws Exception {
  6.                 /*ArrayList<String> list = new ArrayList<String>();
  7.                 list.add("sdfwec");
  8.                 list.getClass().getMethod("add", Object.class).invoke(list, 1);*/
  9.                     ArrayList<Integer> list = new ArrayList<Integer>();
  10.                     list.add(0);
  11.                 list.getClass().getMethod("add", Object.class).invoke(list, "ssss");
  12.                 System.out.println("list:" + list.get(0));
  13.                 System.out.println("list:" + list.get(1));
  14.                 System.out.println("list:" + list.get(0).getClass().getName());
  15.                 System.out.println("list:" + list.get(1).getClass().getName());
  16.                 
  17.             }
  18.         }
复制代码
嗯,你说的没错,是我刚才弄糊涂了。我又测试了一下,如果你这里将String和Integer换一下位置,如上面没注释的,除了最后一句,其他编译没有错误。最后一句也报了相同的错误。具体原因,我也不太清楚,但是我记得曾经看过关于反射的一点看法,反射是很脆弱的,即编译器很难帮助人们发现程序中的错误。任何错误只能在运行时才被发现,并导致异常。所以,我觉得它内部应该有一定的限定了,是不是没有完全擦出泛型的信息呢?这个还有待思考。

作者: 小黑黑    时间: 2013-3-26 10:14
  1. package cn.conpany.test;

  2. import java.lang.reflect.InvocationTargetException;
  3. import java.util.ArrayList;
  4. import java.util.Collection;

  5.         public class RefectColl {
  6.             public static void main(String[] args) throws Exception {
  7.                     ArrayList<Integer> list = new ArrayList<Integer>();
  8.                     list.add(0);
  9.                 list.getClass().getMethod("add", Object.class).invoke(list, "ssss");
  10.                 System.out.println("list:" + list.get(0));
  11.                 System.out.println("list:" + list.get(1));
  12.                 System.out.println("list:" + list.getClass().getMethod("get", int.class).invoke(list, 0));
  13.                 System.out.println("list:" + list.get(1).getClass().getName());
  14.                 
  15.             }
  16.         }
  17.        
  18.        
复制代码
再给你一个有趣的程序,你可以试着运行,每次异常出现的结果和打印的结果都会换位置,如图:












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