首頁 > 歷史

計算機語言中的語法糖——JAVA

作者:由 華清遠見西安 發表于 歷史日期:2022-11-01

計算機中print是什麼

語法糖

(Syntactic Sugar),也稱糖衣語法,指在計算機語言中新增的某種語法,這種語法對語言本身功能來說沒有什麼影響,只是為了方便程式設計師的開發,提高開發效率。

說白了,語法糖就是對現有語法的一個封裝。

我們所熟悉的程式語言中幾乎都會包含語法糖,當然 JAVA 也不例外。一般來說Java中的語法糖主要有以下幾種:

泛型與型別擦除

自動裝箱與拆箱

變長引數

增強for迴圈

內部類

列舉類

計算機語言中的語法糖——JAVA

泛型與型別擦除

Java語言並不是一開始就支援泛型的。在早期的JDK中,只能透過Object類是所有型別的父類和強制型別轉換來實現泛型的功能。強制型別轉換的缺點就是把編譯期間的問題延遲到執行時,JVM並不能為我們提供編譯期間的檢查。

在JDK1。5中,Java語言引入了泛型機制。但是這種泛型機制是透過型別擦除來實現的,即Java中的泛型只在程式原始碼中有效(原始碼階段提供型別檢查),在編譯後的位元組碼中自動用強制型別轉換進行替代。也就是說,Java語言中的泛型機制其實就是一顆語法糖,相較與C++、C#相比,其泛型實現實在是不那麼優雅。

/*** 在原始碼中存在泛型*/publicstaticvoid main(String[] args) { Map map = newHashMap(); map。put(“hello”,“你好”); String hello = map。get(“hello”); System。out。println(hello);}

當上述原始碼被編譯為class檔案後,泛型被擦除且引入強制型別轉換

publicstaticvoid main(String[] args) { HashMap map = newHashMap(); //型別擦除 map。put(“hello”, “你好”); String hello = (String)map。get(“hello”);//強制轉換 System。out。println(hello);}

泛型與型別擦除

Java中的自動裝箱與拆箱指的是基本資料型別與他們的包裝型別之間的相互轉換。

我們知道Java是一門面向物件的語言,在Java世界中有一句話是這麼說的:“萬物皆物件”。但是Java中的基本資料型別卻不是物件,他們不需要進行new操作,也不能呼叫任何方法,這在使用的時候有諸多不便。

因此Java為這些基本型別提供了包裝類,並且為了使用方便,提供了自動裝箱與拆箱功能。自動裝箱與拆箱在使用的過程中,其實是一個語法糖,內部還是呼叫了相應的函式進行轉換。

下面程式碼演示了自動裝箱和拆箱功能:

publicstaticvoid main(String[] args) { Integer a = 1; int b = 2; int c = a + b; System。out。println(c);}

經過編譯後,程式碼如下

publicstaticvoid main(String[] args) { Integer a = Integer。valueOf(1); // 自動裝箱 byte b = 2; int c = a。intValue() + b;//自動拆箱 System。out。println(c);}

自動裝箱與拆箱

所謂變長引數,就是方法可以接受長度不定確定的引數。變長引數特性是在JDK1。5中引入的,使用變長引數有兩個條件,一是變長的那一部分引數具有相同的型別,二是變長引數必須位於方法引數列表的最後面。變長引數同樣是Java中的語法糖,其內部實現是Java陣列。

publicclassVarargs{ publicstaticvoidprint(String。。。 args) { for(String str : args){ System。out。println(str); } } publicstaticvoid main(String[] args) { print(“hello”, “world”); }}

編譯為class檔案後如下,從中可以很明顯

看出變長引數內部是透過陣列實現的

publicclassVarargs{ publicVarargs() { } publicstaticvoidprint(String。。。 args) { String[] var1 = args; int var2 = args。length; //增強for迴圈的陣列實現方式 for(int var3 = 0; var3 < var2; ++var3) { String str = var1[var3]; System。out。println(str); } } publicstaticvoid main(String[] args) { //變長引數轉換為陣列 print(newString[]{“hello”, “world”}); }}

變長引數

增強for迴圈與普通for迴圈相比,功能更強並且程式碼更簡潔。增強for迴圈的物件要麼是一個數組,要麼實現了Iterable介面。這個語法糖主要用來對陣列或者集合進行遍歷,其在迴圈過程中不能改變集合的大小。

publicstaticvoid main(String[] args) { String[] params= newString[]{“hello”,“world”}; //增強for迴圈物件為陣列 for(String str : params){ System。out。println(str); } List lists = Arrays。asList(“hello”,“world”); //增強for迴圈物件實現Iterable介面 for(String str : lists){ System。out。println(str); }}

編譯後的class檔案為

publicstaticvoid main(String[] args) { String[] params= newString[]{“hello”, “world”}; String[] lists = params; int var3 = params。length; //陣列形式的增強for退化為普通for for(int str = 0; str < var3; ++str) { String str1 = lists[str]; System。out。println(str1); } List var6 = Arrays。asList(newString[]{“hello”, “world”}); Iterator var7 = var6。iterator(); //實現Iterable介面的增強for使用iterator介面進行遍歷 while(var7。hasNext()) { String var8 = (String)var7。next(); System。out。println(var8); }}

增強for迴圈

內部類就是定義在一個類內部的類 Java語言中之所以引入內部類,是因為有些時候一個類只在另一個類中有用,我們不想讓其在另外一個地方被使用。內部類之所以是語法糖,是因為其只是一個編譯時的概念,一旦編譯完成,編譯器就會為內部類生成一個單獨的class檔案,名為outer$innter。class。

publicclassOuter{ classInner{ }}

使用javac編譯後,生成兩個class檔案:

Outer。class和Outer$Inner。class

其中Outer$Inner。class的內容如下:

classOuter$Inner{ Outer$Inner(Outer var1) { this。this$0 = var1; }}

內部類分為四種:成員內部類、區域性內部類、匿名內部類、靜態內部類,每一種都有其用法。

內部類

列舉型別就是一些具有相同特性的類常量。java中類的定義使用class,列舉類的定義使用enum。在Java的位元組碼結構中,其實並沒有列舉型別,列舉型別只是一個語法糖,在編譯完成後被編譯成一個普通的類。這個類繼承java。lang。Enum,並被final關鍵字修飾。

publicenumFruit{ APPLE,ORINGE}

使用jad對編譯後的class檔案進行反編譯後得到:

//繼承java。lang。Enum並宣告為finalpublicfinalclassFruitextendsEnum{ publicstaticFruit[] values() { return(Fruit[])$VALUES。clone(); } publicstaticFruit valueOf(String s) { return(Fruit)Enum。valueOf(Fruit, s); } privateFruit(String s, int i) { super(s, i); } //列舉型別常量 publicstaticfinalFruit APPLE; publicstaticfinalFruit ORANGE; privatestaticfinalFruit $VALUES[];//使用陣列進行維護 static { APPLE = newFruit(“APPLE”, 0); ORANGE = newFruit(“ORANGE”, 1); $VALUES = (newFruit[] { APPLE, ORANGE }); }}

Java遠不止這些語法糖,JDK7、JDK8新增的新特性都有很多高階的語法糖。