Java5泛型——仅仅是编译时检查

用代码说话:

  1. package orz.caikanxp;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import org.junit.Test;
  5. public class TestGeneric {
  6.     
  7.     // 创建一个ArrayList对象
  8.     private Object list = new ArrayList();
  9.     
  10.     // 声明3个类型参数各不相同的List变量引用。
  11.     private List oList = (List) this.list;
  12.     private List<String> sList = (List<String>) this.list;
  13.     private List<Boolean> bList = (List<Boolean>) this.list;
  14.     
  15.     // 用于测试的3种不同类型的数据
  16.     private Object o = new Object();
  17.     private String s = "hello";
  18.     private Boolean b = true;
  19.     // 无编译错误,有警告——未提供类型参数
  20.     @Test
  21.     public void testListAdd() throws Exception {
  22.         this.oList.add(o);
  23.         this.oList.add(s);
  24.         this.oList.add(b);
  25.     }
  26.     // 注释的语句有会有编译错误——类型不匹配
  27.     @Test
  28.     public void testStringListAdd() throws Exception {
  29.         // this.sList.add(o);
  30.         this.sList.add(s);
  31.         // this.sList.add(b);
  32.     }
  33.     // 注释的语句有会有编译错误——类型不匹配
  34.     @Test
  35.     public void testBooleanListAdd() throws Exception {
  36.         // this.bList.add(o);
  37.         // this.bList.add(s);
  38.         this.bList.add(b);
  39.     }
  40.     
  41.     // 编译运行均正常
  42.     @Test
  43.     public void testListGet() throws Exception {
  44.         // 先往ArrayList对象中添加测试数据
  45.         this.testListAdd();
  46.         // 取出数据并使用Object类型变量引用。
  47.         Object o0 = this.oList.get(0);
  48.         Object o1 = this.oList.get(1);
  49.         Object o2 = this.oList.get(2);
  50.         
  51.         System.out.println("testListGet");
  52.         System.out.println(o0.getClass());
  53.         System.out.println(o1.getClass());
  54.         System.out.println(o2.getClass());
  55.         System.out.println();
  56.     }
  57.     
  58.     // 编译正常,运行时抛出异常——java.lang.ClassCastException
  59.     // 引用变量的声明类型为String,取出数据的实际运行时类型为Object
  60.     @Test
  61.     public void testStringListGet0() throws Exception {
  62.         this.testListAdd();
  63.         String s0 = this.sList.get(0);
  64.         
  65.         System.out.println("testStringListGet0");
  66.         System.out.println(s0.getClass());
  67.         System.out.println();
  68.     }
  69.     // 编译运行均正常
  70.     // 引用的变量声明类型和取出数据的实际运行时类型均为String
  71.     @Test
  72.     public void testStringListGet1() throws Exception {
  73.         this.testListAdd();
  74.         String s1 = this.sList.get(1);
  75.         
  76.         System.out.println("testStringListGet1");
  77.         System.out.println(s1.getClass());
  78.         System.out.println();
  79.     }
  80.     
  81.     // 编译正常,运行时抛出异常——java.lang.ClassCastException
  82.     // 引用变量的声明类型为String,取出数据的实际运行时类型为Boolean
  83.     @Test
  84.     public void testStringListGet2() throws Exception {
  85.         this.testListAdd();
  86.         String s2 = this.sList.get(2);
  87.         
  88.         System.out.println("testStringListGet2");
  89.         System.out.println(s2.getClass());
  90.         System.out.println();
  91.     }
  92.     
  93.     // 编译运行均正常
  94.     // 引用变量的声明类型为根超类Object,任何实际运行时类型都能引用
  95.     @Test
  96.     public void testStringListGetObject() throws Exception {
  97.         this.testListAdd();
  98.         Object o0 = this.sList.get(0);
  99.         Object o1 = this.sList.get(1);
  100.         Object o2 = this.sList.get(2);
  101.         
  102.         System.out.println("testStringListGetObject");
  103.         System.out.println(o0.getClass());
  104.         System.out.println(o1.getClass());
  105.         System.out.println(o2.getClass());
  106.         System.out.println();
  107.     }
  108.     
  109.     // 要从List<String>中取出Boolean数据该怎么办呢?
  110.     @Test
  111.     public void testStringListGetBoolean() throws Exception {
  112.         this.testListAdd();
  113.         // 这种强制转换行不通,方法返回的声明类型是String,引用变量的类型是Boolean
  114.         // 编译器会检查发现Boolean不是String子类,没有继承关系不允许强制转换。
  115.         // Boolean b2 = (Boolean)this.sList.get(2);
  116.         // 可以通过这个办法回避囧……
  117.         // 先用临时根超类变量引用
  118.         Object o2 = this.sList.get(2);
  119.         // 再对临时根超类变量进行转换
  120.         Boolean b2 = (Boolean) o2;
  121.         
  122.         // 结果证明取出的值确实是Boolean类型
  123.         System.out.println("testStringListGetBoolean");
  124.         System.out.println(b2.getClass());
  125.         System.out.println();
  126.     }
  127. }

JUnit4测试输出结果:

  1. testListGet
  2. class java.lang.Object
  3. class java.lang.String
  4. class java.lang.Boolean
  5. testStringListGet1
  6. class java.lang.String
  7. testStringListGetObject
  8. class java.lang.Object
  9. class java.lang.String
  10. class java.lang.Boolean
  11. testStringListGetBoolean
  12. class java.lang.Boolean

注意:

上面的代码第11行创建的ArrayList对象未指定类型参数;但是即使指定了类型参数,运行的结果也是完全相同的!

因为创建的对象与“类型参数”是无关的,唯一的不同是编译时返回的“声明类型”。

甚至可以把11行换成如下语句,运行的结果和之前也是完全一致的,而不会报错:

  1.     private Object list = new ArrayList<java.util.Date>();

结论:

Java5中泛型仅仅是编译时检查的,要小心使用哦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值