一、簡介
【概念】
語法糖(Syntactic sugar),指計算機語言中新增的某種語法,這種語法對語言的功能沒有影響,但是更方便程式設計師使用。語法糖讓程式更加簡潔,有更高的可讀性。
【特點】
只存在於編譯期, 在編譯器將.java原始檔編譯成.class位元組碼時, 會進行解語法糖操作, 還原最原始的基礎語法結構;
不會提供實質性的功能改進,但是能提高我們開發的效率。
二、常見語法糖
1、自動裝箱與拆箱
【概念】
自動裝箱:將基本資料型別自動轉換成對應的包裝類(一般用於基本型別資料處於需要物件的環境中);
自動拆箱:將包裝類自動轉換成對應的基本資料型別(當需要值時)。
【出現原因】
Java早年設計缺陷。基礎型別是資料,不是物件,也不是Object的子類。把一個基本型別包裝成一個類,可以使這個型別具有很多可以呼叫的方法。
Java向麵像物件語言的靠近。其實Java還不算是很純的物件導向的語言。真正的物件導向,是沒有基本資料型別的。它只有一種型別,就是物件。
在泛型中,基本型別是不可以做泛型引數的。
【原理】
自動裝箱都是透過包裝類的valueOf()方法來實現的;
自動拆箱都是透過包裝類物件的xxxValue()來實現的。
【示例】
Integer i = 10; //裝箱,等價於Integer i = Integer.valueOf(10); int n = i; //拆箱,等價於int n = i.intValue();
【使用場景】
當我們把基本資料型別放入集合類中的時候,會進行自動裝箱;
包裝類與基本資料型別進行比較運算,是先將包裝類進行拆箱成基本資料型別,然後進行比較的;
兩個包裝型別之間的運算,會被自動拆箱成基本型別進行。
【注意事項】
所有整型包裝類物件之間值的比較,全部使用equals方法比較,原因如下,詳請見包裝類的快取機制;
public static void main(String[] args) { Integer i1 = 1222; Integer i2 = 1222; Integer i3 = 12; Integer i4 = 12; System.out.println("i1 是否等於 i2:" + (i1==i2)) ; System.out.println("i3 是否等於 i4:" + (i3==i4)) ; }
i1 是否等於 i2:false i3 是否等於 i4:true
一個for迴圈中有大量拆裝箱操作,會浪費很多資源。
2、可變引數
【概述】
在具體實際開發過程中,有時方法中引數的個數是不確定的。
【語法】
methodName({paramList},paramType...paramName)
methodName:方法名稱;
paramList:方法的固定引數列表;
paramType:可變引數的型別;
...:宣告可變引數的標識;
paramName:可變引數名稱。
【注意】可變引數必須定義在引數列表的最後。
【例子】
public class StudentTestMethod { // 定義輸出考試學生的人數及姓名的方法 public void print(String...names) { int count = names.length; // 獲取總個數 System.out.println("本次參加考試的有"+count+"人,名單如下:"); for(int i = 0;i < names.length;i++) { System.out.println(names[i]); } } public static void main(String[] args) { // TODO Auto-generated method stub StudentTestMethod student = new StudentTestMethod(); student.print("張強","李成","王勇"); // 傳入3個值 student.print("馬麗","陳玲"); } }
3、泛型
3.1 簡介
【概述】
泛型的本質是引數化型別,它提供了編譯時型別安全監測機制,透過這個機制,我們可以在編譯時檢查型別安全,泛型所有的強制轉換都是自動、隱式的,只要編譯時沒有問題,執行時就不會出現ClassCastException(型別轉換異常),極大地提高程式碼的可讀性、複用性及安全性。
【作用】
將型別明確的事情延後到建立物件或呼叫方法時,再去明確的特殊的型別;
呼叫方法時,不用強轉物件、寫很多重複方法;
提高程式碼複用性和可讀性(一套程式碼可支援不同的型別,不用強轉,更加簡潔);
提高程式安全性。
【使用場景】
使用在不想寫多個過載函式的場景;
使用在使用者希望返回他自定義型別的返回值場景。例如:Json 返回 Java bean ;
在使用反射的應用中,也經常使用泛型。例如:Class<T> ;
使用在約束物件型別的場景,用來定義邊界(T extends ...)。例如:JDK 集合 List,Set ;
使用在網頁、資源分析或返回的場景。
3.2 泛型擦除
【概念】
在JVM中沒有泛型這一概念, 只有普通方法和普通類, 所有泛型類的泛型引數都會在編譯時期被擦除, 所以泛型類並沒有自己獨有的Class類物件。
【示例】
public class GenericType { public static void main(String[] args) { ArrayList<String> arrayString=new ArrayList<String>(); ArrayList<Integer> arrayInteger=new ArrayList<Integer>(); // List<Integer> 和 List<String> 型別在編譯後,都會變成 List 型別(原始型別) System.out.println(arrayString.getClass()==arrayInteger.getClass()); //true } }