1. 程式人生 > >19 Java語法糖的味道

19 Java語法糖的味道

《深入理解Java虛擬機器:JVM高階特性與最佳實踐(第2版)》10.3節 語法糖不會提供實質性功能改進,但或能提高效率、提升語法嚴謹性、減少編碼出錯機會

泛型與型別擦除

泛型是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屬性中的位元組碼進行擦除,實際上元資料中保留了泛型資訊,這是能通過反射手段取得引數化型別的根本依據 基於這種方法實現的泛型稱偽泛型 當泛型遇見過載
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語言中的特徵簽名,內容包括方法名稱、引數順序、引數型別 此外還有位元組碼中的特徵簽名,內容包括方法名稱、引數順序、引數型別、方法返回值、受查異常表

自動裝箱、拆箱與遍歷迴圈

/**
 * 自動裝箱、拆箱與遍歷迴圈
 */
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");
}