语法糖
所谓的 语法糖 ,其实就是指 java 编译器把 *.java 源码编译为 *.class 字节码的过程中,自动生成和转换的一些代码,主要是为了减轻程序员的负担.
注意,以下代码的分析,借助了 javap 工具,idea 的反编译功能,idea 插件 jclasslib 等工具。另外,编译器转换的结果直接就是 class 字节码,只是为了便于阅读,给出了 几乎等价 的 java 源码方式,并不是编译器还会转换出中间的 java 源码,切记。
1 默认构造器
编译成class后的代码:
编译成class后的代码:
2 自动拆装箱
这个特性是 JDK 5 开始加入的,代码片段1 :
这段代码在 JDK 5 之前是无法编译通过的,必须改写为 代码片段2 :
显然之前版本的代码太麻烦了,需要在基本类型和包装类型之间来回转换(尤其是集合类中操作的都是包装类型),因此这些转换的事情在 JDK 5 以后都由编译器在编译阶段完成。即 代码片段1 都会在编译阶段被转换为 代码片段2
3 泛型集合取值
泛型也是在 JDK 5 开始加入的特性,但 java 在编译泛型代码后会执行 泛型擦除 的动作,即泛型信息
在编译为字节码之后就丢失了,实际的类型都当做了 Object 类型来处理:
所以在取值时,编译器真正生成的字节码中,还要额外做一个类型转换的操作:
如果前面的 x 变量类型修改为 int 基本类型那么最终生成的字节码是:
还好这些麻烦事都不用自己做。
擦除的是字节码上的泛型信息,可以看到 LocalVariableTypeTable 仍然保留了方法参数泛型的信息
4 可变参数
可变参数也是 JDK 5 开始加入的新特性: 例如:
可变参数 String... args 其实是一个 String[] args ,从代码中的赋值语句中就可以看出来。 同样 java 编译器会在编译期间将上述代码变换为:
- 注意 如果调用了 foo() 则等价代码为 foo(new String[]{}) ,创建了一个空的数组,而不会
传递 null 进去
5 foreach 循环
仍是 JDK 5 开始引入的语法糖,数组的循环:
而集合的循环:
实际被编译器转换为对迭代器的调用:
- 注意 foreach 循环写法,能够配合数组,以及所有实现了 Iterable 接口的集合类一起使用,其
中 Iterable 用来获取集合的迭代器(Iterator )
6 枚举类
JDK 7 新增了枚举类,以前面的性别枚举为例:
转换后代码:
7 匿名内部类
源代码:
转换后的代码:
引用局部变量的匿名内部类,源代码:
- 注意 这同时解释了为什么匿名内部类引用局部变量时,局部变量必须是 final 的:因为在创建Candy11$1 对象时,将 x 的值赋值给了 Candy11$1 对象的 val属性, 不应该再发生变 了,如果变 ,那么 x 属性没有机会再跟着一起变化
__EOF__

本文链接:https://www.cnblogs.com/LiPengFeiii/p/15213248.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~