19 Java語法糖的味道
阿新 • • 發佈:2019-02-15
《深入理解Java虛擬機器:JVM高階特性與最佳實踐(第2版)》10.3節
語法糖不會提供實質性功能改進,但或能提高效率、提升語法嚴謹性、減少編碼出錯機會
1. 入參不同出參相同
public static void method(List<String> list){}
public static void method(List<Integer> list){}
以上程式碼不能被編譯
因編譯後引數List<String>和List<Integer>被擦除,變成相同的原生型別List<E>,導致兩個方法的特徵簽名和描述符完全相同,不可共存於一個Class檔案
2. 入參不同出參不同
public static String method(List<String> list){}
public static Int method(List<Integer> list){}
以上程式碼可以被編譯和執行
因兩個方法的返回值不同,即,雖特徵簽名相同但描述符不同,可共存於一個Class檔案
上述方法特徵簽名指Java語言中的特徵簽名,內容包括方法名稱、引數順序、引數型別
此外還有位元組碼中的特徵簽名,內容包括方法名稱、引數順序、引數型別、方法返回值、受查異常表
包裝類“==”運算不遇到算術運算時不會自動拆箱,equals()方法不處理資料轉型關係
泛型與型別擦除
泛型是JDK1.5新增特性,本質是引數化型別(Parametersized Type)的應用,即資料型別被指定為引數 這種引數型別可用在類、介面和方法的建立中,分別稱泛型類、泛型介面和泛型方法 泛型技術在C#和Java中的根本性分歧 C#泛型: 無論在程式原始碼、編譯後的IL(Intermediate Language,中間語言,這時泛型是一個佔位符)、執行期的CLR都切實存在 List<int>與List<String>是兩個不同的型別,它們在系統執行期生成,有自己的虛方法表和型別資料 這種實現稱型別膨脹 基於這種方法實現的泛型稱真實泛型 Java泛型: 只在程式原始碼中存在,在編譯後的位元組碼檔案中替換為原生型別(Raw Type,也稱裸型別),且在相應位置插入強制轉型程式碼 對於執行期Java語言ArrayList<int>與ArrayList<String>是同一個類 Java泛型技術實際上是Java的一顆語法糖 Java泛型實現方法稱型別擦除 注,所謂的擦除僅是對方法Code屬性中的位元組碼進行擦除,實際上元資料中保留了泛型資訊,這是能通過反射手段取得引數化型別的根本依據 基於這種方法實現的泛型稱偽泛型 當泛型遇見過載自動裝箱、拆箱與遍歷迴圈
/**
* 自動裝箱、拆箱與遍歷迴圈
*/
public static void main(String... args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4);
// 若JDK1.7可寫成 List<Integer> list =[1, 2, 3, 4];
int sum = 0;
for (int i : list) {
sum += i;
}
System.out.println(sum);
}
/** * 自動裝箱、拆箱與遍歷迴圈編譯後 */ public static void main(String[] args) { List list = Arrays.asList(new Integer[]{ Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4) }); int sum = 0; for (Iterator localIterator = list.iterator(); localIterator.hasNext(); ) { int i = ((Integer) localIterator.next()).intValue(); sum += i; } System.out.println(sum); }
包裝類“==”運算不遇到算術運算時不會自動拆箱,equals()方法不處理資料轉型關係
條件編譯
Java語言條件編譯的實現: 根據布林常量值真假,編譯器把分支中不成立的程式碼塊消除掉 這一工作在編譯器解除語法糖階段(com.sun.tools.javac.comp.Lower類)完成/**
* 條件編譯
*/
public static void main(String[] args) {
if (true) {
System.out.println(" block 1");
} else {
System.out.println(" block 2");
}
}
/**
* 條件編譯反編譯
*/
public static void main(String[] args) {
System.out.println(" block 1");
}