一、了解一下javac编译的详解过程
![](https://i-blog.csdnimg.cn/blog_migrate/4ae2e77a136e26e4b55656230b7c50e1.png)
(1)词法、语法分析
(2)符号填充表(目前这点知识我不是很理解)
(3)注解处理器
(4)语义分析与字节码生成
a) 标注检查
int a = 1;
boolean b = false;
char c = 2;
int d = a + c;
int d = b + c;
char d = a + c;
b) 数据及控制流分析
c) 语法糖
(4)字节码生成
二、Java语法糖的味道
语法糖虽然不会提供实质性的功能改进,但是它们或能提供效率,或能提升语法的严谨性,或能减少编码出错的机会。但是大量添加和使用“含糖”的语法,容易让程序员产生依赖,无法看清程序代码的真实面目。
(1)泛型与类型擦除
泛型早期在Java语言中没有出现时,只能通过Object是所有类型的父类和类型强制转换两个特点的配合来实现类型转化。例如:在哈希表的存取中,1.5之前使用HashMap的get()方法,返回值就是一个Object对象,由于Java语言里面所有的类型都继承于java.lang.Object,所以Object转型成任何对象都是有可能的。但是因为有无限可能性,许多ClassCastException的风险就会转嫁到程序的运行期间。
泛型重载(编译不通过)
public class GenericType{
public static void method(List<String> list){
System.out.print("invoke method(List<String> list)");
}
public static void method(List<Integer> list){
System.out.print("invoke method(List<Integer> list)");
}
}
编译不通过,泛型在编译阶段进行擦除,变成原生类型List<E>,擦除 动作导致这两种方法的特征签名变得一模一样。
(2)自动装箱、拆箱与遍历循环
源代码:
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4);
//如果在JDK 1.7中,还有另外一种语法糖
//能让上面这句话进一步简写成List<Integer> list = [1, 2, 3, 4]
int sum = 0;
for (Integer i : list) {
sum += i;
}
System.out.println(sum);
}
编译后的代码:
public static void main(String[] args) {
List<Integer> list = Arrays.asList(new Integer[]{
Integer.valueOf(1),
Integer.valueOf(2),
Integer.valueOf(3),
Integer.valueOf(4)
});
int sum = 0;
for (Iterator localIterator = list.iterator();localIterator.hasNext();){
int i = ((Integer) localIterator.next()).intValue();
sum += i;
}
System.out.println(sum);
}
装箱:基本类型变为包装类型,例如:Integer n = 1;
拆箱:包装类型变为基本类型,例如:int i = n;
重点:包装类重新赋值会创建新的对象,因为每一个包装类型中value都被final修饰的!例如Integer类中:private final int value;
(3) 条件编译
源代码:
public static void main(String[] args) {
if (true) {
System.out.println("block 1");
} else {
System.out.println("block 2");
}
}
编译后的代码:
public static void main(String[] args) {
System.out.println("block 1");
}
只能使用条件为常量的if语句才能达到上述效果,编译器将会把分支中不成立的代码块消除掉,这一过程在编译阶段完成!
重点理解:在前端编译器中,“优化”手段主要用于提升程序的编码效率,之所以把Javac这类将Java代码转变为字节码的编译器称做“前端编译器”,是因为它只完成了从程序到抽象语法树或中间代码的生成,而在此之后,还有一组内置于虚拟机内部的“后端编译器”完成从字节码生成本地机器码的过程,就是即时编译器或JIT编译器,这个编译器的编译速度及编译结果的优劣,是衡量虚拟机性能一个很重要的指标!