編譯過程可分爲3個步驟:java
解析步驟包含了詞法分析和語法分析兩個過程。程序員
詞法分析
是將源代碼的字符流轉變爲標記(Token)集合,標記是編譯過程的最小元素。 語法分析
是根據Token序列構建抽象語法樹的過程。 抽象語法樹
是一種用來描述程序代碼語法結構的樹形表示方式,語法樹中的每個節點都表明着程序代碼中的一個語法結構,例如包、類型、修飾符、運算符、接口等。優化
符號表是由一組符號地址和符號信息構成的表格。符號表中登記的信息在編譯的不一樣階段都要用到。在語義分析中,符號表所登記的內容將用於語義檢查和產生中間代碼。在目標代碼生成階段,當對符號名進行地址分配時,符號表是地址分配的依據。插件
JDK1.6之中提供了一組插入式註解處理器的標準API在編譯期間對註解進行處理,能夠把它看作是一組編譯器插件,在這些插件中,能夠讀取、修改、添加抽象語法樹中的任意元素。若這些插件在處理註解期間對語法樹進行了修改,編譯器將回到解析及填充符號表的過程從新處理,直到全部插入式註解處理器都沒有再對語法樹進行修改成止,每一次循環稱爲一個Round。code
語法樹能表示一個結構正確的源程序的抽象,但沒法保證資源程序是符合邏輯的。而語義分析的主要任務
是對結構上正確的源程序進行上下文有關性質的審查,如類型審查。接口
在Javac的編譯過程當中,語義分析過程分爲標註檢查
以及數據及控制流分析
兩個步驟。 標註檢查步驟檢查的內容包括諸如變量使用前是否已被聲明、變量與賦值之間的數據類型是否可以匹配
等。 在標註檢查步驟中,還有一個重要的動做稱爲變量摺疊
。例如: 在代碼中寫下:資源
int a = 1 + 2;
在通過變量摺疊以後,1 + 2
會被摺疊爲字面量3
。因此在代碼裏定義int a = 1 + 2
比起直接定義int a = 3
並不會增長程序運行期的運算量。編譯器
數據及控制流分析是對程序上下文邏輯更進一步的驗證,他能夠檢查出諸如程序局部變量在使用前是否有賦值、方法的每條路徑是否都有返回值、是否全部的受檢查異常都被正確處理了等問題。it
語法糖(Syntactic Sugar)
,也稱糖衣語法,由英國計算機科學家Peter J.Landin發明的一個術語,指在計算機語言中添加的某種語法,這種語法對語言的功能並無影響,可是更方便程序員使用。 Java中的語法糖會在編譯階段還原
回簡單的基礎語法結構,這個過程成爲解語法糖
。編譯
字節碼生成是Javac編譯過程的最後一個階段,此階段編譯器還進行了少許的代碼添加和轉換工做。實例構造器<init>()
和類構造器<clinit>()
就是在這個階段添加到語法樹中的。完成了對語法樹的遍歷和調整以後,生成最終的Class文件。
泛型的本質是參數化類型,即所所操做的數據類型被指定爲一個參數。這種參數類型能夠應用在類、接口和方法的建立中,分別被稱爲泛型類、泛型接口和泛型方法。 Java中泛型只存在於源代碼中,在編譯階段會擦除泛型,替換爲原來的原生類型(Raw Type,也稱裸類型),並在相應地方插入強制轉型代碼。
包裝類的「==」運算在不遇到算術運算的狀況下不會自動拆箱
,它們的equals()方法不處理數據轉型
。