1、概述:
編譯過程的編譯器:
- 1、前端編譯器:Sun的Javac、Eclipse JDT中的增量式編譯器(ECJ) (.java檔案變為*.class過程)
- 2、JIT編譯器:HotSpot VM 的C1、C2編譯器(.class檔案變成機器碼的過程)
- 3、AOT編譯器:GNU Compiler for the java(GCJ)、Excelsior JET(.java檔案直接變成機器碼的過程)
2、Javac編譯器
編譯器過程大緻分為三個過程
- 1、解析與填充符号表過程
- 2、插入式注解處理器的注解處理過程
- 3、分析與位元組碼生成過程
2.1 解析與填充符号表
1、詞法、文法分析
2、填充符号表
總結:不恰當比喻---将不同大小蘋果先檢出來,按照放入不同筐内。
2.2 注解處理器
注解與普通代碼類似,根據不同注解重複修改文法樹。(塑像進行雕刻,而注解是刀,塑像是文法樹)
2.3 語義分析與位元組碼生成
表示代碼正确,還要符合類型之間關系
int a=1;
boolean b = false;
char c = 2;
int d = a+c (編譯正确)
int d = b+c(編譯異常)
1、标注檢查
常量折疊:例如 int a= 1+2; 代表是 int a =3
2、資料及控制流分析
3、解文法糖
定義:增加程式可讀性,對功能沒有的影響的文法
4、位元組碼生成
3、java文法糖的味道
3.1、泛型與類型擦除
真實泛型:就是泛型一直存在到運作期,List<int>與List<String>就是不同類型,它們有自己的虛方法表和類型資料。
僞泛型:java語言的泛型,它隻存在于源碼中,後期編譯會替換原來的原生類型,并且在相應位置插入強制轉換代碼,這就是java類型擦除
package com.jack;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) throws Throwable{
Map<String, String> map = new HashMap<String,String>();
map.put("hello", "你好");
map.put("how are you?", "點點滴滴");
System.out.printf(map.get("hello"));
System.out.printf(map.get("how are you?"));
}
}
編譯成位元組碼檔案後反編譯為:
package com.jack;
import java.util.HashMap;
public class Main {
public static void main(String[] arg) throws Throwable {
HashMap arg0 = new HashMap();
arg0.put("hello", "你好");
arg0.put("how are you?", "點點滴滴");
System.out.printf((String) arg0.get("hello"), new Object[0]);
System.out.printf((String) arg0.get("how are you?"), new Object[0]);
}
}
List<Integer> 和List<String>代表同一個類
import java.util.List;
public class GenericTypes {
public static void method(List<String> list) {
System.out.printf("invoke method(List<String> list)");
}
public static void method(List<Integer> list) {
System.out.printf("invoke method(List<Integer> list)");
}
}
會出現編譯錯誤 :Erasure of method method(List<Integer>) is the same as another method in type (表示擦拭泛型後代表相同類)
3.3 自動裝箱、拆箱與周遊循環
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) throws Throwable{
List<Integer> list = Arrays.asList(1,2,3,4);
int sum =0;
for (int i: list){
sum +=i;
}
System.out.println(sum);
}
}
編譯後的代碼
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class Main {
public static void main(String[] arg) throws Throwable {
List arg0 = Arrays
.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4)});
int arg1 = 0;
int arg3;
for (Iterator arg2 = arg0.iterator(); arg2.hasNext(); arg1 += arg3) {
arg3 = ((Integer) arg2.next()).intValue();
}
System.out.println(arg1);
}
}
以上一共包含泛型、自動裝箱、自動拆箱、周遊循環與變長參數的五種文法糖
public class Main {
public static void main(String[] args) throws Throwable{
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 222;
Integer f = 222;
Long g = 3L;
System.out.printf("c==d : %s\n", c==d);
System.out.printf("e==f : %s\n", e==f);
System.out.printf("e.equals(f) : %s\n",e.equals(f));
System.out.printf("c == (a+b) : %s\n", c==(a+b));
System.out.printf("c.equals(a+b): %s\n", c.equals(a+b));
System.out.printf("g == (a + b): %s\n", g == (a + b));
System.out.printf("g.equals(a+b): %s\n", g.equals(a+b));
}
}
位元組碼反編譯:
public class Main {
public static void main(String[] arg) throws Throwable {
Integer arg0 = Integer.valueOf(1);
Integer arg1 = Integer.valueOf(2);
Integer arg2 = Integer.valueOf(3);
Integer arg3 = Integer.valueOf(3);
Integer arg4 = Integer.valueOf(222);
Integer arg5 = Integer.valueOf(222);
Long arg6 = Long.valueOf(3L);
System.out.printf("c==d : %s\n", new Object[]{Boolean.valueOf(arg2 == arg3)});
System.out.printf("e==f : %s\n", new Object[]{Boolean.valueOf(arg4 == arg5)});
System.out.printf("e.equals(f) : %s\n", new Object[]{Boolean.valueOf(arg4.equals(arg5))});
System.out.printf("c == (a+b) : %s\n",
new Object[]{Boolean.valueOf(arg2.intValue() == arg0.intValue() + arg1.intValue())});
System.out.printf("c.equals(a+b): %s\n",
new Object[]{Boolean.valueOf(arg2.equals(Integer.valueOf(arg0.intValue() + arg1.intValue())))});
System.out.printf("g == (a + b): %s\n",
new Object[]{Boolean.valueOf(arg6.longValue() == (long) (arg0.intValue() + arg1.intValue()))});
System.out.printf("g.equals(a+b): %s\n",
new Object[]{Boolean.valueOf(arg6.equals(Integer.valueOf(arg0.intValue() + arg1.intValue())))});
}
日志:
c==d : true
e==f : false
e.equals(f) : true
c == (a+b) : true
c.equals(a+b): true
g == (a + b): true
g.equals(a+b): false
總結:
- 1、如果是對象還是用equals進行比較保險。
- 2、無論是Integer,Long的裝箱拆箱都是基于【-128,127】範圍有效
- Integer a = 128;
- Integer b =128;
- a==b 為false
3.3、條件編譯
public class Main {
public static void main(String[] args) throws Throwable{
if(true){
System.out.printf("子產品一");
} else {
System.out.printf("子產品二");
}
}
}
編譯後:
public class Main {
public static void main(String[] args) throws Throwable{
System.out.printf("子產品一");
}
}