程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程解疑 >> java基礎-java泛型擦除原因,何為遷移兼容性

java基礎-java泛型擦除原因,何為遷移兼容性

編輯:編程解疑
java泛型擦除原因,何為遷移兼容性

看了thinking in java 裡的泛型篇,搞不懂裡面講的泛型的核心動機是遷移兼容性,為了使泛化客戶端能夠使用非泛化庫類,反之亦然。
作者分別了向後兼容性和遷移兼容性,可是沒用例子說明什麼樣是遷移兼容性,能舉個例子說明一下如果泛型不擦除,就無法遷移代碼嗎?十分感謝!

最佳回答:


1、你要理解java編譯和解釋執行的過程。在各過程中,范型的存在性、存在方式、被處理方式。
2、編譯器編譯源代碼時,會檢查范型,防止類型出錯。
例如:List usernames = new ArrayList();將不能通過編譯。
它將源代碼編譯為字節碼,這時候的字節碼,與沒有使用范型編譯過來的字節碼比較,多出了一些范型信息。
但是這些范型信息的有無,對於JVM是一樣的(如果不考慮反射)。
List usernames = new ArrayList();
Object o = usernames;
List ints = (List)o;//warning
usernames.add("avril lavigne");
ints.add(100);
以上代碼,ints和usernames指向同一個列表,但是卻可以添加字符串和整型對象。
這段代碼應該會加深你對范型的理解。
3、 對“拭去法”的理解,並不只是簡單的將范型信息擦出。
public class Hello {
T t;
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
Type[] types = Hello.class.getTypeParameters();
System.out.println(types[0]);
Hello h = new Hello<>();
h.t = "";
h.getClass().getDeclaredField("t").set(h, 1);;
System.out.println(h.t);
}
}
這段代碼通過編譯,並輸出
T
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at generic.Hello.main(Hello.java:13)
也就是說,字節碼被載入jvm後,字段的類型仍然保持為T。這也驗證了范型是參數化類型的說法。
如果再加兩行代碼
Hello h2 = new Hello<>();
h2.t = (Integer)(Object)h.t;
也將通過編譯,然而運行卻報異常。
說明在實例化對象的時候,動態的將字段的類型進行了設定,和的信息對運行時產生了影響!!!
同一個類型實例化的對象,相同的屬性類型卻不能匹配!!!
有范型和沒范型,編譯得到的字節碼有本質的不同。jvm載入後,類中含有參數化類型。
這個類型化參數,是在運行時動態綁定的!
范型沒有被拭去?是的。"拭去法"並不能簡單的理解。
更准確的理解應該是,編譯時,對於類定義,范型作為類型的參數化信息,並不決定類型。
拭去,指的是在類定義時,范型不決定被定義類的類型,而不是指范型信息被擦除!范型信息仍然是該類的一部分!!!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved