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