JDK1.5引入的泛型,减少了类型强转的代码,增加了编译检查,提高了代码的健壮性。
但在某些情况,泛型检查会出乎意料的“丢失”,由此可引发难以发现的bug。
1 public class GenericDefectTest {
2
3 public void test(final Map<String, String> map) {
4 System.out.println(map.get("a"));// 这行可以正常执行
5 System.out.println(map.get("b"));// 运行到这行才会报错
6 for (Map.Entry<String, String> entry : map.entrySet()) {
7 System.out.println(entry.getValue());
8 }
9 }
10
11 public static void main(final String args[]) throws Exception {
12 GenericDefectTest genericTest = new GenericDefectTest();
13
14 Map<String, Object> map = new HashMap<String, Object>();
15 map.put("a", "a");
16 map.put("b", 1);
17 // new GenericTest().test(map);// 这里有编译验证,如果取消注释会出错。没有问题
18
19 // 但是如果用反射调用的话,就没有验证了,在实际使用这个值的时候才会报错
20 Method test = GenericDefectTest.class.getDeclaredMethod("test", Map.class);
21 test.invoke(genericTest, map);
22 }
23 }
我们期望程序执行到第三行就会报错,但实际进行到第五行才会报错。
反编译查看class
1 public class GenericDefectTest
2 {
3 public void test(Map<String, String> map)
4 {
5 System.out.println((String)map.get("a"));
6 System.out.println((String)map.get("b"));
7 for (Map.Entry entry : map.entrySet())
8 System.out.println((String)entry.getValue());
9 }
10
11 public static void main(String[] args) throws Exception
12 {
13 GenericDefectTest genericTest = new GenericDefectTest();
14
15 Map map = new HashMap();
16 map.put("a", "a");
17 map.put("b", Integer.valueOf(1));
18
19 Method test = GenericDefectTest.class.getDeclaredMethod("test", new Class[] { Map.class });
20 test.invoke(genericTest, new Object[] { map });
21 }
22 }
可以看到泛型仍然存在于函数定义中。
这可以说是一个Java泛型的"缺陷",实际使用中需要特别注意。