本篇文章将围绕Java中的编译器,深入浅出的解析前端编译的流程、泛型、条件编译、增强for循环、可变长参数、lambda表达式等语法糖原理
Java中的编译器不止一种,Java编译器可以分为:前端编译器、即时编译器和提前编译器
最为常见的就是前端编译器javac,它能够将Java源代码编译为字节码文件,它能够优化程序员使用起来很方便的语法糖
即时编译器是在运行时,将热点代码直接编译为本地机器码,而不需要解释执行,提升性能
提前编译器将程序提前编译成本地二进制代码
<init>,<clinit>
**方法,并根据上述信息生成字节码文件前端编译流程图
源码分析
代码位置在JavaCompiler的compile方法中
将操作的数据类型指定为方法签名中一种特殊参数,作用在方法、类、接口上时称为泛型方法、泛型类、泛型接口
Java中的泛型是类型擦除式泛型,泛型只在源代码中存在,在编译期擦除泛型,并在相应的地方加上强制转换代码
与具现化式泛型(不会擦除,运行时也存在泛型)对比
增强for循环 -> 迭代器
可变长参数 -> 数组装载参数
泛型擦除后会在某些位置插入强制转换代码
自动装箱、拆箱的错误用法
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
//true
System.out.println(c == d);//范围小,在缓冲池中
//false
System.out.println(e == f);//范围大,不在缓冲池中,比较地址因此为false
//true
System.out.println(c == (a + b));
//true
System.out.println(c.equals(a + b));
//false
System.out.println(g == (b + a));
//true
System.out.println(g.equals(a + b));
布尔类型 + if语句 : 根据布尔值类型的真假,编译器会把分支中不成立的代码块消除(解语法糖)
编写函数式接口
@FunctionalInterface
interface LambdaTest {
void lambda();
}
编写测试类
public class Lambda {
private int i = 10;
public static void main(String[] args) {
test(() -> System.out.println("匿名内部类实现函数式接口"));
}
public static void test(LambdaTest lambdaTest) {
lambdaTest.lambda();
}
}
使用插件查看字节码文件
生成了一个私有静态的方法,这个方法中很明显就是lambda中的代码
在使用lambda表达式的类中隐式生成一个静态私有的方法,这个方法代码块就是lambda表达式中写的代码
执行class文件时带上参数java -Djdk.internal.lambda.dumpProxyClasses 包名.类名
即可显示出这个匿名内部类
使用invokedynamic
生成了一个实现函数式接口的匿名内部类对象,在重写函数式接口的方法实现中调用使用lambda表达式类中隐式生成的静态私有方法
本篇文章以Java中编译器的分类为开篇,深入浅出的解析前端编译的流程,Java中泛型、增强for循环、可变长参数、自动拆装箱、条件编译以及Lambda等语法糖的原理
前端编译先将字符流转换为token流,再将token流转换为抽象语法树,填充符号表的符号信息、符号地址,然后注解处理器处理特殊注解(比如Lombok生成get、set方法),对语法树发生写改动则要重新解析、填充符号,接着检查语义静态信息以及常量折叠,对运行时程序进行动态检查,再解语法糖,生成init实例方法、clinit静态方法,最后生成字节码文件
Java中为了兼容之前的版本使用类型擦除式的泛型,在编译期间擦除泛型并在相应位置加上强制转换,想为基本类型使用泛型只能搭配自动拆装箱一起使用,性能有损耗且在运行时无法获取泛型类型
增加for循环则是使用迭代器实现,并在适当位置插入强制转换;可变长参数则是创建数组进行装载参数
自动拆装箱提供基本类型与包装类的转换,但包装类尽量不使用==,这是去比较引用地址,同类型比较使用equals
条件编译会在if-else语句中根据布尔类型将不成立的分支代码块消除
lambda原理则是通过**invokeDynamic
**指令动态生成实现函数式接口的匿名对象,匿名对象重写函数时接口方法中调用使用lambda表达式类中隐式生成的静态私有的方法(该方法就是lambda表达式中的代码内容)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。