JAVA語法糖和語法糖編譯
先簡單瞭解下定義
語法糖
語法糖(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迴圈原理
對於陣列,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反編譯後:
原文連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/36/viewspace-2812223/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 語法糖
- Java語法糖詳解Java
- Java 中的語法糖,真甜。Java
- vue 常用語法糖Vue
- Golang常用語法糖Golang
- 大話 語法糖
- vue.js語法糖Vue.js
- Java基礎-try-with-resource語法糖Java
- Vue v-model語法糖Vue
- Java 中12個常見的語法糖Java
- C# 語法糖 ver2C#
- Golang接收者方法語法糖Golang
- 重新認識 async/await 語法糖AI
- angular 新語法糖學習一Angular
- JavaScript 中一顆有毒的語法糖JavaScript
- Kotlin的語法糖(一)基礎篇Kotlin
- ObjC中語法糖的趣味應用OBJ
- Vue3.2 setup語法糖總結Vue
- 裝飾器、語法糖、修復技術
- 傻瓜式vuex語法糖kiss-vuexVue
- vue3 setup語法糖 擴充套件Vue套件
- C#中檢查null的語法糖C#Null
- Java語法糖: 使用 try-with-resources 語句安全地釋放資源Java
- 用Java寫編譯器(1)- 詞法和語法分析Java編譯語法分析
- 細數Java的語法糖(一): 用於字串拼接的 "+" 運算子Java字串
- 細數Java的語法糖(一): 用於字串拼接的 “+” 運算子Java字串
- Vue3 使用setup語法糖時, 元件name命名Vue元件
- C# 中居然也有切片語法糖,太厲害了C#
- 傳說中 VUE 的“語法糖”到底是啥?Vue
- 【Vue3.0】關於 script setup 語法糖的用法Vue
- 為什麼說ES6的class是語法糖?
- C#12中的Collection expressions(集合表示式語法糖)C#Express
- SG :一個簡單的PHP語法糖擴充套件PHP套件
- C#中檢查null的語法糖,非常實用C#Null
- Hollis原創|不瞭解這12個語法糖,別說你會JavaJava
- Vue 3 的 setup語法糖到底是什麼東西?Vue
- 十分鐘帶你欣賞ES6語法糖
- 兩種語法糖,搞定Vue元件Prop的雙向繫結Vue元件