第10章 早期(編譯期)優化
javac編譯過程:
1、解析與填充符號表過程
詞法、語法分析 將源代碼的字條流轉變為標記(Token)集合。如“int a = b + 2”這名代碼包含了6個標記,分別是int a = b + 2
填充符號表
2、注解處理器
3、語義分析與字節碼生成
標注檢查 包括諸如變量使用前是否已被聲明、變量與賦值之 間的數據類型是否能夠匹配,還有一個重要的動作稱為常量折疊
數據及控制流分析 對程序上下文邏輯更進一步的驗證,它可以檢查出諸如程序局部變量在使用前是否有賦值、方法的每條路徑是否都有返回值、是否所有的受查異常都被正確處理了第問題。
解語法糖 泛型、變長參數、自動裝箱/拆箱等
java中的泛型只在程序源碼中存在,在編譯后的字節碼中就已經替換為原來的原生類型了,并且在相應的地方插入強制類型轉換代碼。
字節碼生成
Java方法中的泛型
Java的泛型在編譯后就擦除了,所以如下代碼會編譯出錯:

因為參數List<Integer>和List<String>編譯之后都被搾除了,變成了一樣的原生類型 List,導致這兩種方法的牲簽名變得一模一樣。修改代碼如下:

便可以編譯,方法的重載成功。Class文件方法表(method_info)的數據結構時,方法重載要求方法具備不同的特征簽名,返回值并不包含在方法的特征簽名之中,所以返回值不參與重載選擇,但在Class文件格式中,只要描述符不是完全一致的兩個方法就可以共存。也就是說,兩個方法如果有相同的名稱和特征簽名,那它們也是可以合法地共存于一個Class文件中的。執行結果如下:

說明Java還是能夠正常執行重載的泛型的方法,Java編譯進已經把泛型擦除了,為什么還能進行重載的方法呢?

如圖 28 35行為調用Java的編譯后代碼,
28行為第一次調用JavaTest.test(ss),參數為List<Integer>的時候。
35行為第二次調用JavaTest.test(ssa),參數為List<String>的時候。
說明雖然編譯會擦除泛型,但也會為泛型的調用方法進行相應的編譯。
新聞熱點
疑難解答