摘要:提供給了用戶大量的語法糖,比如泛型自動裝箱拆箱循環(huán)變長參數(shù)內(nèi)部類枚舉類斷言新特性方法引用等解語法糖語法糖的存在主要是方便開發(fā)人員使用。
首先,部分總結(jié)文字引用 簡書作者:Eric新之助 。鏈接:https://www.jianshu.com/p/4de08deb6ba4
已獲得授權(quán)
先簡單了解下定義
語法糖語法糖(Syntactic Sugar),也叫糖衣語法,是英國計(jì)算機(jī)科學(xué)家彼得·約翰·蘭達(dá)(Peter J. Landin)發(fā)明的一個(gè)術(shù)語。指的是,在計(jì)算機(jī)語言中添加某種語法,這種語法能使程序員更方便的使用語言開發(fā)程序,同時(shí)增強(qiáng)程序代碼的可讀性,避免出錯的機(jī)會。
幾乎每種語言都提供語法糖,它只是編譯器實(shí)現(xiàn)的一些小把戲罷了,編譯期間以特定的字節(jié)碼或者特定的方式對這些語法做一些處理,開發(fā)者就可以直接方便地使用了。這些語法糖雖然不會提供實(shí)質(zhì)性的功能改進(jìn),但是它們或能提高性能、或能提升語法的嚴(yán)謹(jǐn)性、或能減少編碼出錯的機(jī)會。Java提供給了用戶大量的語法糖,比如泛型、自動裝箱/拆箱、foreach循環(huán)、變長參數(shù)、內(nèi)部類、枚舉類、斷言、JAVA8新特性(lambda、stream、方法引用等)......
語法糖的存在主要是方便開發(fā)人員使用。但其實(shí),Java 虛擬機(jī)并不支持這些語法糖,這些語法糖在編譯階段就會被還原成簡單的基礎(chǔ)語法結(jié)構(gòu),這個(gè)過程就是解語法糖。
說到編譯,大家肯定都知道,Java 語言中,javac命令可以將后綴名為.java的源文件編譯為后綴名為.class的可以運(yùn)行于 Java 虛擬機(jī)的字節(jié)碼。
如果你去看com.sun.tools.javac.main.JavaCompiler的源碼,你會發(fā)現(xiàn)在compile()中有一個(gè)步驟就是調(diào)用desugar(),這個(gè)方法就是負(fù)責(zé)解語法糖的實(shí)現(xiàn)的。
學(xué)習(xí)語法糖原理最好的辦法就是反編譯看源碼~
反編譯工具:
IDEA默認(rèn)反編譯內(nèi)置插件: JD-IntelliJ
對java8支持良好的反編譯工具: procyon-decompiler
使用方法 : java -jar (jar包路徑)procyon-decompiler-0.5.30.jar(class文件路徑)*.class
只支持到j(luò)dk1.5的反編譯工具: jad
使用方法 : jad -o -8 -r -d(輸出反編譯文件路徑) -sjava (class文件路徑)下面看看語法糖和三種反編譯器編譯后的代碼 可變長度參數(shù)
可變參數(shù)由數(shù)組實(shí)現(xiàn)
Ps:可變長度參數(shù)必須作為方法參數(shù)列表中的的最后一個(gè)參數(shù)且方法參數(shù)列表中只能有一個(gè)可變長度參數(shù)
對于數(shù)組,foreach是用普通for循環(huán)實(shí)現(xiàn)的。
說明在對有實(shí)現(xiàn)Iterable接口的對象采用foreach語法糖的話,編譯器會將這個(gè)for關(guān)鍵字轉(zhuǎn)化為對目標(biāo)的迭代器使用。
所以如果想要自己自定義的類可以采用foreach語法糖就要實(shí)現(xiàn)Iterable接口了。
可以看到在自動裝箱的時(shí)候,Java虛擬機(jī)會自動調(diào)用Integer的valueOf方法;
在自動拆箱的時(shí)候,Java虛擬機(jī)會自動調(diào)用Integer的intValue方法。這就是自動拆箱和自動裝箱的原理
代碼:
IDEA反編譯:
procyon-decompiler反編譯:
jad反編譯:
泛型與類型擦除對于java虛擬機(jī)來說,他根本不認(rèn)識Map
類型擦除的主要過程如下:
將所有的泛型參數(shù)用其最左邊界(最頂級的父類型)類型替換。 移除所有的類型參數(shù)。
代碼:
IDEA反編譯:
procyon-decompiler反編譯:
jad反編譯:
泛型與重載泛型編譯出來的代碼是會把類型擦除的,所以如下的代碼是不能編譯的,是因?yàn)閰?shù)List
那么如果加上返回類型呢?
上面這段代碼,IDE無法編譯通過,javac編譯可以通過。
網(wǎng)上找到一段引用:
在《Java虛擬機(jī)規(guī)范第二版》(JDK 1.5修改后的版本)的“§4.4.4
Signatures”章節(jié)及《Java語言規(guī)范第三版》的“§8.4.2 Method
Signature”章節(jié)中分別都定義了字節(jié)碼層面的方法特征簽名,以及Java代碼層面的方法特征簽名,特征簽名最重要的任務(wù)就是作為方法獨(dú)一無二不可重復(fù)的ID,在Java代碼中的方法特征簽名只包括了方法名稱、參數(shù)順序及參數(shù)類型,而在字節(jié)碼中的特征簽名還包括方法返回值及受查異常表。
根據(jù)上面的例子說明:由于List
Java枚舉編譯后實(shí)際上是生成了一個(gè)類,該類繼承了 java.lang.Enum
代碼:
IDEA反編譯:
procyon-decompiler反編譯:
jad反編譯:
內(nèi)部類Java的內(nèi)部類也是一個(gè)語法糖,它僅僅是一個(gè)編譯時(shí)的概念,outer.java里面定義了一個(gè)內(nèi)部類inner,一旦編譯成功,就會生成兩個(gè)完全不同的.class文件了,分別是outer.class和outer$inner.class。所以內(nèi)部類的名字完全可以和它的外部類名字相同。
代碼:
IDEA反編譯:
procyon-decompiler反編譯:
jad反編譯:
Parsing /Users/dasouche/Downloads/product/springboot-demo/target/classes/com/example/demo/DemoOutClass.class...Parsing inner class /Users/dasouche/Downloads/product/springboot-demo/target/classes/com/example/demo/DemoOutClass$InnerClass.class... Generating /Users/dasouche/Desktop/jad158g.mac.intel/com/example/demo/DemoOutClass.java斷言
代碼:
IDE反編譯:
procyon-decompiler反編譯:
jad反編譯:
JAVA8新特性中語法糖Lambda表達(dá)式在Java 8中首先會生成一個(gè)私有的靜態(tài)函數(shù),這個(gè)私有的靜態(tài)函數(shù)干的就是Lambda表達(dá)式里面的內(nèi)容
代碼:
IDEA反編譯:
procyon-decompiler反編譯:
jad反編譯 報(bào)錯:
用javap反編譯后:
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/76757.html
摘要:但其實(shí),虛擬機(jī)并不支持這些語法糖。方式為每個(gè)泛型類型創(chuàng)建唯一的字節(jié)碼表示,并且將該泛型類型的實(shí)例都映射到這個(gè)唯一的字節(jié)碼表示上。GitHub 2.5k Star 的Java工程師成神之路 ,不來了解一下嗎); GitHub 2.5k Star 的Java工程師成神之路 ,真的不來了解一下嗎); GitHub 2.5k Star 的Java工程師成神之路 ,真的確定不來了解一下嗎); 本文從 ...
摘要:但其實(shí),虛擬機(jī)并不支持這些語法糖。方式為每個(gè)泛型類型創(chuàng)建唯一的字節(jié)碼表示,并且將該泛型類型的實(shí)例都映射到這個(gè)唯一的字節(jié)碼表示上。GitHub 2.5k Star 的Java工程師成神之路 ,不來了解一下嗎); GitHub 2.5k Star 的Java工程師成神之路 ,真的不來了解一下嗎); GitHub 2.5k Star 的Java工程師成神之路 ,真的確定不來了解一下嗎); 本文從 ...
摘要:但其實(shí),虛擬機(jī)并不支持這些語法糖。方式為每個(gè)泛型類型創(chuàng)建唯一的字節(jié)碼表示,并且將該泛型類型的實(shí)例都映射到這個(gè)唯一的字節(jié)碼表示上。GitHub 2.5k Star 的Java工程師成神之路 ,不來了解一下嗎); GitHub 2.5k Star 的Java工程師成神之路 ,真的不來了解一下嗎); GitHub 2.5k Star 的Java工程師成神之路 ,真的確定不來了解一下嗎); 本文從 ...
摘要:操作對應(yīng)字節(jié)碼中的個(gè)字節(jié)我們可以看到最關(guān)鍵的操作其實(shí)就是調(diào)用的其實(shí)是類的方法,此方法的入?yún)㈩愋褪牵祷刂殿愋褪?,翻譯過來就是類的方法,執(zhí)行完后將獲得的結(jié)果做了,檢查返回的對象類型是否是。 語法糖(Syntactic Sugar)的出現(xiàn)是為了降低我們編寫某些代碼時(shí)陷入的重復(fù)或繁瑣,這使得我們使用語法糖后可以寫出簡明而優(yōu)雅的代碼。在Java中不加工的語法糖代碼運(yùn)行時(shí)可不會被虛擬機(jī)接受,因此...
摘要:因此,對應(yīng)地我們可以翻譯這段二進(jìn)制字節(jié)碼為這樣的代碼注意,這段代碼并不能通過編譯,因?yàn)樵创a這一層是不允許直接繼承的,這個(gè)繼承過程只允許在編譯器內(nèi)部解語法糖的過程中被編譯器添加,添加之后的類才會有的訪問標(biāo)識符。 語法糖(Syntactic Sugar)的出現(xiàn)是為了降低我們編寫某些代碼時(shí)陷入的重復(fù)或繁瑣,這使得我們使用語法糖后可以寫出簡明而優(yōu)雅的代碼。在Java中不加工的語法糖代碼運(yùn)行時(shí)可...
閱讀 3121·2023-04-26 01:58
閱讀 962·2021-11-24 09:38
閱讀 3293·2021-09-03 10:29
閱讀 723·2021-08-21 14:10
閱讀 1498·2019-08-30 15:44
閱讀 3096·2019-08-30 14:10
閱讀 3222·2019-08-29 16:32
閱讀 1485·2019-08-29 12:48