1. 程式人生 > >Java語法糖(一)

Java語法糖(一)

級別 類型擦除 簽名 轉換 uga pre 它的 out fde

概述

  語法糖(Syntactic Sugar):主要作用是提高編碼效率,減少編碼出錯的機會。

  解語法糖發生在Java源碼被編譯成Class字節碼的過程中,還原回簡單的基礎語法結構。

語法糖之一:泛型(Generics)

  Java中的泛型又稱為類型擦除,它只在Java源碼中存在,被編譯成字節碼後,就已經替換為原生類型了,並在相應的地方加入強制類型轉換。

  例如:

public class GenericTypes {
    /*
     * 兩個mothod1方法不能被編譯,因為List<Integer>和List<String>被編譯成class文件後都被擦除了,
     * 變成了一樣的原生類型List<T>,擦除之後兩個方法的簽名一樣。
     
*/ public static void mothod1(List<Integer> list) { } public static void mothod1(List<String> list) { } /* * 在jdk1.7 * 兩個mothod2方法不能被編譯,因為List<Integer>和List<String>被編譯成class文件後都被擦除了, * 變成了一樣的原生類型List<T>,擦除之後兩個方法的簽名一樣。返回值不參與重載選擇 * * Sun JDK1.6中Javac才能編譯成功 * 在Class文件格式中,只要描述符不是完全一致的兩個方法就可以共存。
*/ public static String mothod2(List<String> list) { return ""; } public static Integer mothod2(List<Integer> list) { return 1; } }

語法糖之二:自動拆箱和裝箱、Foreach、變長參數

  例如:

public class Foreach_Varargs {
    public static void main(String[] args) {
        List
<Integer> list = Arrays.asList(1, 2, 3, 4);//變長參數(Varargs) int sum = 0; for(int i : list) { //遍歷循環Foreach sum += i; } System.out.println(sum); } /* * 反編譯之後的代碼 * 1、變長參數還原為數組類型的參數:Arrays.asList(...) ----> new Integer[]{...} * 2、Foreach還原為叠代器實現 * 3、自動拆箱和裝箱還原為Integer.valueOf()和Integer.intValue()方法 * public static void main(String[] args) { java.util.List<Integer> list = java.util.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); } */ }

  一個更復雜的自動裝箱拆箱的栗子:

public class Autoboxing {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 321;
        Integer f = 321;
        Long g = 3L;
        System.out.println(c == d); //(1)
        System.out.println(e == f); //(2)
        System.out.println(c == (a + b)); //(3)
        System.out.println(c.equals(a + b)); //(4)
        System.out.println(g == (a + b)); //(5)
        System.out.println(g.equals(a + b)); //(6)
    }
    /*
     * 反編譯後的代碼
     * 
     * 包裝類的“==”運算在不遇到算數運算的情況下不會自動拆箱;
     * equals方法不處理數據轉型的關系。
     * 
     * 在 Java 中,== 比較的是對象引用,而 equals 比較的是值。
     * 
     * 一、(1)為true,(2)為false原因:
     *      IntegerCache:把-128到127(可調)的整數都提前實例化了,不管創建多少個這個範圍內的Integer用ValueOf出來的都是同一個對象;
     *      用來節省內存和提高性能。這種 Integer緩存策略僅在自動裝箱(autoboxing)的時候有用,使用構造器創建的 Integer 對象不能被緩存。
     *      這個緩存會在 Integer 類第一次被使用的時候被初始化出來.是什麽原因選擇這個 -128 到 127 這個範圍呢?因為這個範圍的整數值是使用最廣泛的。
     *      Byte,Short,Long 有固定範圍: -128 到 127。對於 Character, 範圍是 0 到 127。除了 Integer 可以通過參數改變範圍外,其它的都不行
     *      
     *      不在緩存範圍的會新new Integer對象。
     * 二、(3)為true,(5)為true
     *      自動拆箱,相當於數值類型int
     * 三、(4)為true
     *      a,b先拆箱計算數值和,再將計算結果裝箱為Integer
     * 四、(5)為false
     *      g為Long類型,a + b為Integer,類型不一致
     * 五、(6)為false, g為Long類型,a + b為Integer,類型不一致,返回false
            public boolean equals(Object obj) {
                if (obj instanceof Long) {
                    return value == ((Long)obj).longValue();
                }
                return false;
            }     
     *      
     public class Autoboxing {
       public static void main(String[] args) {
          Integer a = Integer.valueOf(1);
          Integer b = Integer.valueOf(2);
          Integer c = Integer.valueOf(3);
          Integer d = Integer.valueOf(3);
          Integer e = Integer.valueOf(321);
          Integer f = Integer.valueOf(321);
          Long g = Long.valueOf(3L);
          System.out.println(c == d);
          System.out.println(e == f);
          System.out.println(c.intValue() == a.intValue() + b.intValue());
          System.out.println(c.equals(Integer.valueOf(a.intValue() + b.intValue())));
          System.out.println(g.longValue() == (long)(a.intValue() + b.intValue()));
          System.out.println(g.equals(Integer.valueOf(a.intValue() + b.intValue())));
       }
    }
    */
}

語法糖之三:條件編譯

  栗子:

public class ifdef {
    public static void main(String[] args) {
        final boolean isCompile = true;
        if(isCompile) {
            System.out.println("11111");
        } else {
            System.out.println("2222");
        }
    }
    /*
     * 條件編譯
     * System.out.println("2222"); 不會編譯
     * Java只能實現語句基本塊級別的條件編譯,而無法實現根據條件調整整個Java類的結構。
     * 
     * 反編譯後的代碼:
     * public class ifdef {
           public static void main(String[] args) {
              boolean isCompile = true;
              System.out.println("11111");
           }
        }
     */
}

除以上外,語法糖還有:內部類、枚舉類、斷言語句、對枚舉和字符串的switch支持(1.7)、try語句中定義和關閉資源(1.7)等,接下來繼續Java語法糖系列。

  

Java語法糖(一)