在上一篇Lombok经常用,但是你知道它的原理是什么吗?简单介绍了注解处理器,是用来处理编译期的注解的一个工具,我们只是自己生成了一些代码,但是和Lombok却不一样,因为Lombok是在原有类的基础上增加了一些类,你那么Lombok是如何做到修改原有类的内容呢?接下来我们就再进一步了解Lombok的原理。
Javac原理
既然我们是在编译期对类进行操作了,那么我们就需要了解在Java中Javac到底对程序做了什么。Javac对代码编译的过程其实就是用Java来写的,我们可以查看其源码对其简单的分析,如何下载源码,Debug源码这里我就不进行分析了,推荐一篇文章写的挺好的。Javac 源码调试教程。
编译过程大致分为了三个阶段
- 解析与填充符号表
- 注解处理
- 分析与字节码生成
这三个阶段的交互过程如下图所示。
解析与填充符号表
这一步骤是两个步骤,包括了解析和填充符号,其中解析是分为词法分析和语法分析两个步骤。
词法分析和语法分析
词法分析就是将源代码的字符流转变为Java中的标记(Token)集合,单个字符是程序编写过程中最小的元素,而标记(Token)则是编译过程中最小的元素,关键字、变量名、字面量、运算符都可以成为标记(Token)。比如在Java中int a = b+2
,这段代码则表示了6个标记Token
,分别是int、a、=、b、+、2
。虽然关键字int是由三个字符构成的,但是它只是一个Token,不可以再拆分了。
语法分析是根据Token序列构造抽象对象树的过程,抽象语法树(Abstract syntax tree),是一种用来描述代码语法结构的树形表示方法,语法树的每一个节点都代表着程序代码中的一个语法结构,例如包、类型、修饰符、运算符、接口、返回值甚至是代码注释都是一个语法结构。
语法分析分析出来的树结构是由JCTree
来表示的,我们可以看一下它的子类有哪些。
我们自己建一个类,可以观察它在编译过程中用树结构表示是一种怎样的结构。
public class HelloJvm {
private String a;
private String b;
public static void main(String[] args) {
int c = 1+2;
System.out.println(c);
print();
}
private static void print(){
}
}
大家注意我划红线的地方,可以看到这些都是JCTree的子类。我们可以知道编译期的树是以JCCompilationUnit
为根节点,然后作为类的构成元素例如方法、私有变量、class类,这些都是作为树的构成一种。