Javac编译器详解
一、了解一下javac编译的详解过程
(1)词法、语法分析
(2)符号填充表(目前这点知识我不是很理解)
(3)注解处理器
(4)语义分析与字节码生成
a) 标注检查
1 2 3 | int a = 1 ; boolean b = false ; char c = 2 ; |
1 2 3 | 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的风险就会转嫁到程序的运行期间。
泛型重载(编译不通过)
1 2 3 4 5 6 7 8 9 | 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)自动装箱、拆箱与遍历循环
源代码:
1 2 3 4 5 6 7 8 9 10 | 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); } |
编译后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) 条件编译
源代码:
1 2 3 4 5 6 7 | public static void main(String[] args) { if ( true ) { System.out.println( "block 1" ); } else { System.out.println( "block 2" ); } } |
编译后的代码:
1 2 3 | public static void main(String[] args) { System.out.println( "block 1" ); } |
只能使用条件为常量的if语句才能达到上述效果,编译器将会把分支中不成立的代码块消除掉,这一过程在编译阶段完成!
重点理解:在前端编译器中,“优化”手段主要用于提升程序的编码效率,之所以把Javac这类将Java代码转变为字节码的编译器称做“前端编译器”,是因为它只完成了从程序到抽象语法树或中间代码的生成,而在此之后,还有一组内置于虚拟机内部的“后端编译器”完成从字节码生成本地机器码的过程,就是即时编译器或JIT编译器,这个编译器的编译速度及编译结果的优劣,是衡量虚拟机性能一个很重要的指标!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架