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泛型的"缺陷",實際使用中需要特別注意。