Javac编译器是把 *.java 文件转换为 *.class 文件,是一个前端编译器;对应着有一种把字节码转变为机器码的编译器,称为JIT编译器(Just In Time Compiler),比如 HotSpot VM 的C1、C2编译器;把 *.java 文件编译成机器码的编译器称为静态提前编译器;

  Javac编译器编译的过程可以为3个过程:

    1、解析与填充符号表:

      这个过程又可以细分为词法分析、语法分析和填充符号表;

      词法分析:词法分析是将源代码的字符流转变为标记(Token)集合,单个字符是程序编写过程的最小元素,而标记则是编译过程的最小元素,关键字、变量名、字面量、运算符都可以成为标记。

      语法分析:语法分析是根据Token序列构造抽象语法树的过程,抽象语法树(Abstract Syntax Tree)是一种用来描述程序代码语法结构的树形表示方式,语法树的每一个节点都代表着程序代码中的一个语结构。

      符号表(Symbol Tree):符号表是一组符号地址和符号信息构造的表格,符号表登记的信息在编译的不同阶段都要用到。

    2、插入式注解处理器的注解处理:插入式注解器相当于编译器的插件,我们可以通过注解处理器读取、修改、添加抽象语法树中的任意元素。如果对抽象语法树进行了修改,编译器将会重新回到解析及填充符号表的过程重新处理,直到所有插入式注解处理器都没有再对语法树进行修改为止。

    3、语义分析与字节码生成过程:语法分析的主要任务是对结构上正确的源程序进行上下文有关性质的审核,保证源代码程序符合逻辑。

      语义分析又可以细分为 标注检查和数据及控制流分析:

        标注检查:标注检查检查的内容包括变量使用前是否被声明、变量与赋值之间的数据类型是否能够匹配,常量折叠(比如 int a = 1 * 2; 会处理为 int a = 3;)等等;

        数据及控制流检查:检查内容有程序局部变量在使用前是否有赋值、方法的每一条路径是否都有返回值,是否所有的受查异常都被正常的处理 等等;

      语法糖:指在计算机语言中添加某种语法,这种语法对语言的功能并没有影响,但是方便程序员使用;

      字节码生成:字节码生成是把前面各个步骤所生成的信息(语法树、符号表)转化成字节码写到磁盘的过程,在这个过程中还进行了不少代码添加和转换的工作,比如生成实例构造器和类构造器;

Java 语法糖

  1、泛型与类型擦除:

    泛型是JDK 1.5 的一项新增特性,它的本质是参数化类型的应用,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口和泛型方法。

    Java的泛型是一种伪泛型,它只存在于程序的源代码中,在编译后的字节码文件中,就已经替换为原来的原生类型。

  2、自动拆箱、装箱和遍历循环:  

    自动装箱、自动拆箱反编译后对应包装类的包装、还原方法;

    遍历循环 反编译后对应 迭代器实现;

    变长参数 反编译后 变成了一个数组类型的参数;

// 以下是源代码,包含了泛型,自动装箱,自动拆箱、遍历循环、变长参数共5种语法糖
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = 0;
for (int i : list) {
sum += i;
}
System.out.println(sum); //反编译后的源代码
List list = Arrays.asList(new Integer[] {
null, null, null, null,
(new Integer[5][3] =
(new Integer[5][2] =
(new Integer[5][1] =
(new Integer[5][0] = Integer.valueOf(1)).valueOf(2)).valueOf(3)).valueOf(4)).valueOf(5) });
int i = 0;
for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
int j = ((Integer)iterator.next()).intValue();
i += j;
}
System.out.println(i);

  3、自动装箱的陷阱:

// 源代码
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L; System.out.println(c == d);
System.out.println(e == f);
System.out.println(c == (a + b));
System.out.println(c.equals(a + b));
System.out.println(g == (a + b));
System.out.println(g.equals(a + b)); // 反编译后的代码
Integer integer1 = Integer.valueOf(1);
Integer integer2 = Integer.valueOf(2);
Integer integer3 = Integer.valueOf(3);
Integer integer4 = Integer.valueOf(3);
Integer integer5 = Integer.valueOf(321);
Integer integer6 = Integer.valueOf(321);
Long l = Long.valueOf(3L); System.out.println((integer3 == integer4));
System.out.println((integer5 == integer6));
System.out.println((integer3.intValue() == integer1.intValue() + integer2.intValue()));
System.out.println(integer3.equals(Integer.valueOf(integer1.intValue() + integer2.intValue())));
System.out.println((l.longValue() == (integer1.intValue() + integer2.intValue())));
System.out.println(l.equals(Integer.valueOf(integer1.intValue() + integer2.intValue()))); // 运行结果
true
false
true
true
true
false //说明
1. 包装类的 “==” 运算在遇到算术运算符会自动拆箱
2. 包装类的 equals 方法先会判断比较的类型是否 instanceof 包装类
3. 当Integer,Long包装类在自动装箱时如果值在 -128 ~ 127 之间时会共享缓存值

 4、条件编译

  javac编译器会把条件分支中永远不会执行的分支消除掉。

笔记:Javac编译器的更多相关文章

  1. java-关于java_home配置,classpath配置和javac,java命令,javac编译器,和java虚拟机之间的关系

    在每个人学习java的第一步,都是安装jdk ,jre,配置java_home,classpath,path. 为什么要做这些?在阅读java-core的时候,看到了原理,p141. 一 关于类的共享 ...

  2. 早期(编译器)优化--javac编译器

    java语言的“编译期”其实是一段“不确定”的操作过程,可能是指一个前端编译器把.java变成.class的过程,也可能是指虚拟机的后端运行期编译器(JLT)把字节码转变成机器码的过程,也有可能是使用 ...

  3. 第一章-Javac编译器介绍

    1.Javac概述 编译器可以将编程语言的代码转换为其他形式,如Javac,将Java语言转换为虚拟机能够识别的.class文件形式.而这种将java源代码(以.java做为文件存储格式)转换为cla ...

  4. Javac编译器详解

    学习<深入了解Java虚拟机>有一段时间了,大概理解了Java从源代码编译到执行出结果的过程,也能明确的知道Java是半解释性语言.在执行源代码时,先通过Javac编译器对源代码进行词法分 ...

  5. 早期javac编译器优化

    学习<深入了解Java虚拟机>有一段时间了,大概理解了Java从源代码编译到执行出结果的过程,也能明确的知道Java是半解释性语言.在执行源代码时,先通过Javac编译器对源代码进行词法分 ...

  6. Javac 编译器

    编译过程 Javac 编译过程大致可以分为1个准备过程和3个处理过程: 准备过程:初始化插入式注解处理器. 解析与填充符号表过程,包括: 词法.语法分析,将源代码的字符流转变为标记集合,构造出抽象语法 ...

  7. 关于Javac编译器的那点事(一)

    Javac是什么? 它是一种编译器,将Java对人非常友好的语言,编译转化对所有机器都非常友好的语言,即:JVM能够识别的语言,也就是Java字节码.而Java字节码,说白了就是一连串二进制数字. J ...

  8. 对openjdk的javac编译器扩展了一个语法糖

    我的扩展功能描述如下: 在java的现有语法中加入var来声明变量,并且可以根据初始化数据来自动类型推导. 举两个例子: 例一: 如下JAVA代码(注意这里的var是新语法): import java ...

  9. JVM系列五(javac 编译器).

    一.概述 我们都知道 *.java 文件要首先被编译成 *.class 文件才能被 JVM 认识,这部分的工作主要由 Javac 来完成,类似于 Javac 这样的我们称之为前端编译器: 但是 *.c ...

随机推荐

  1. 后缀数组 (Suffix Array) 学习笔记

    \(\\\) 定义 介绍一些写法和数组的含义,首先要知道 字典序 . \(len\):字符串长度 \(s\):字符串数组,我们的字符串存储在 \(s[0]...s[len-1]\) 中. \(suff ...

  2. css3 transform + deviceorientation实现图片旋转效果

    1. 陀螺仪deviceorientation的使用,参考<关于陀螺仪deviceorientation>https://segmentfault.com/a/11900000071838 ...

  3. 使用VirtualBox的时候虚拟机无法ping通windows主机,但是主机可以ping通虚拟机

    问题原因是windows开启了防火墙导致的,将windows的防火墙关闭即可. 关闭windows防火墙后会有警告的信息出现,直接无视即可.

  4. iOS - - JSON 和 XML解析

    JSON 和 XML 一.JSON 1.什么是JSON JSON是一种轻量级的数据格式,一般用于数据交互 服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外) 2.JSON的格 ...

  5. org.apache.tomcat.util.net.NioEndpoint,打开的文件过多

    错误信息: 27-Mar-2019 04:20:20.430 严重 [http-nio-8100-Acceptor-0] org.apache.tomcat.util.net.NioEndpoint$ ...

  6. Farseer.net轻量级ORM开源框架 V1.x 教程目录

    本篇教程将以Ver 1.x版本进行详细使用讲解 大家有任何疑问可以加入我们的官方QQ群进行讨论.QQ群:116228666 (Farseer.net开源框架交流) 请注明:Farseer.Net 整个 ...

  7. windows echo命令

    ECHO命令是大家都熟悉的DOS批处理命令的一条子命令,但它的一些功能和用法也许你并不是全都知道,不信你瞧:  1. 作为控制批处理命令在执行时是否显示命令行自身的开关 格式:ECHO [ON|OFF ...

  8. COGS.1200 ganggang的烦恼

    背景 Zhang Gangrui 年纪大了,记性不好,保险箱的密码记不住了,他只记得密码是一个数的阶乘各个位的数相加的和,最后还有个T或F,代表这个数是否为素数,正好,你到他家去了,他请你帮他这个忙, ...

  9. CREATE TABLE AS - 从一条查询的结果中创建一个新表

    SYNOPSIS CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name [ (column_name [, ...] ...

  10. js 删除数组中某一项的几种方法总结

    第一种:改变原数组 借用原生数组方法:splice(index,len,[item])  剪接 借用原生对象方法:delete array[index] + array.slice(0, index) ...