深入浅出JVM(六)之前端编译过程与语法糖原理

本篇文章将围绕Java中的编译器,深入浅出的解析前端编译的流程、泛型、条件编译、增强for循环、可变长参数、lambda表达式等语法糖原理

编译器与执行引擎

编译器

Java中的编译器不止一种,Java编译器可以分为:前端编译器、即时编译器和提前编译器

最为常见的就是前端编译器javac,它能够将Java源代码编译为字节码文件,它能够优化程序员使用起来很方便的语法糖

即时编译器是在运行时,将热点代码直接编译为本地机器码,而不需要解释执行,提升性能

提前编译器将程序提前编译成本地二进制代码

前端编译过程

  • 准备阶段: 初始化插入式注解处理器

  • 处理阶段

    • 解析与填充符号表

      1. 词法分析: 将Java源代码的字符流转变为token(标记)流

        • 字符: 程序编写的最小单位
        • 标记(token) : 编译的最小单位
        • 比如 关键字 static 是一个标记 / 6个字符
      2. 语法分析: 将token流构造成抽象语法树

      3. 填充符号表: 产生符号信息和符号地址

        • 符号表是一组符号信息和符号地址构成的数据结构
        • 比如: 目标代码生成阶段,对符号名分配地址时,要查看符号表上该符号名对应的符号地址
    • 插入式注解处理器的注解处理

      1. 注解处理器处理特殊注解: 在编译器允许注解处理器对源代码中特殊注解作处理,可以读写抽象语法树中任意元素,如果发生了写操作,就要重新解析填充符号表

        • 比如: Lombok通过特殊注解,生成get/set/构造器等方法
    • 语义分析与字节码生成

      1. 标注检查: 对语义静态信息的检查以及常量折叠优化

         int i = 1;
         char c1 = 'a';
         int i2 = 1 + 2;//编译成 int i2 = 3 常量折叠优化
         char c2 = i + c1; //编译错误 标注检查 检查语法静态信息 

        image-20210524202623150.png

      2. 数据及控制流分析: 对程序运行时动态检查

        • 比如方法中流程控制产生的各条路是否有合适的返回值
      3. 解语法糖: 将(方便程序员使用的简洁代码)语法糖转换为原始结构

      4. 字节码生成: 生成<init>,<clinit>方法,并根据上述信息生成字节码文件

前端编译流程图

image-20210524205803664.png

源码分析

image-20210524222754508.png 代码位置在JavaCompiler的compile方法中

image-20210524221445424.png

Java中的语法糖

泛型

将操作的数据类型指定为方法签名中一种特殊参数,作用在方法、类、接口上时称为泛型方法、泛型类、泛型接口

Java中的泛型是类型擦除式泛型,泛型只在源代码中存在,在编译期擦除泛型,并在相应的地方加上强制转换代码

与具现化式泛型(不会擦除,运行时也存在泛型)对比

  • 优点: 只需要改动编译器,Java虚拟机和字节码指令不需要改变

    • 因为泛型是JDK5加入的,为了满足对以前版本代码的兼容采用类型擦除式泛型
  • 缺点: 性能较低,使用没那么方便

    • 为提供基本类型的泛型,只能自动拆装箱,在相应的地方还会加速强制转换代码,所以性能较低

    • 运行期间无法获取到泛型类型信息

      • 比如书写泛型的List转数组类型时,需要在方法的参数中指定泛型类型

         public static <T> T[] listToArray(List<T> list,Class<T> componentType){
                 T[] instance = (T[]) Array.newInstance(componentType, list.size());
                 return instance;
         }
增强for循环与可变长参数

image-20210524213429033.png

增强for循环 -> 迭代器

可变长参数 -> 数组装载参数

泛型擦除后会在某些位置插入强制转换代码

自动拆装箱

自动装箱、拆箱的错误用法

         Integer a = 1;
         Integer b = 2;
         Integer c = 3;
         Integer d = 3;
         Integer e = 321;
         Integer f = 321;
         Long g = 3L;
         //true
         System.out.println(c == d);//范围小,在缓冲池中
         //false
         System.out.println(e == f);//范围大,不在缓冲池中,比较地址因此为false
         //true
         System.out.println(c == (a + b));
         //true
         System.out.println(c.equals(a + b));
         //false
         System.out.println(g == (b + a));
         //true
         System.out.println(g.equals(a + b));
  • 注意:

    1. 包装类重写的equals方法中不会自动转换类型 image-20210524213853321.png

    2. 包装类的 == 就是去比较引用地址,不会自动拆箱

条件编译

布尔类型 + if语句 : 根据布尔值类型的真假,编译器会把分支中不成立的代码块消除(解语法糖)

image-20210524214427206.png

Lambda原理

编写函数式接口

 @FunctionalInterface
 interface LambdaTest {
     void lambda();
 }

编写测试类

 public class Lambda {
     private int i = 10;
 ​
     public static void main(String[] args) {
         test(() -> System.out.println("匿名内部类实现函数式接口"));
     }
 ​
     public static void test(LambdaTest lambdaTest) {
         lambdaTest.lambda();
     }
 }

使用插件查看字节码文件

image-20210524230643123.png 生成了一个私有静态的方法,这个方法中很明显就是lambda中的代码

在使用lambda表达式的类中隐式生成一个静态私有的方法,这个方法代码块就是lambda表达式中写的代码

image-20210524232010510.png 执行class文件时带上参数java -Djdk.internal.lambda.dumpProxyClasses 包名.类名即可显示出这个匿名内部类

image-20210527083659256.png

使用invokedynamic生成了一个实现函数式接口的匿名内部类对象,在重写函数式接口的方法实现中调用使用lambda表达式类中隐式生成的静态私有方法

总结

本篇文章以Java中编译器的分类为开篇,深入浅出的解析前端编译的流程,Java中泛型、增强for循环、可变长参数、自动拆装箱、条件编译以及Lambda等语法糖的原理

前端编译先将字符流转换为token流,再将token流转换为抽象语法树,填充符号表的符号信息、符号地址,然后注解处理器处理特殊注解(比如Lombok生成get、set方法),对语法树发生写改动则要重新解析、填充符号,接着检查语义静态信息以及常量折叠,对运行时程序进行动态检查,再解语法糖,生成init实例方法、clinit静态方法,最后生成字节码文件

Java中为了兼容之前的版本使用类型擦除式的泛型,在编译期间擦除泛型并在相应位置加上强制转换,想为基本类型使用泛型只能搭配自动拆装箱一起使用,性能有损耗且在运行时无法获取泛型类型

增加for循环则是使用迭代器实现,并在适当位置插入强制转换;可变长参数则是创建数组进行装载参数

自动拆装箱提供基本类型与包装类的转换,但包装类尽量不使用==,这是去比较引用地址,同类型比较使用equals

条件编译会在if-else语句中根据布尔类型将不成立的分支代码块消除

lambda原理则是通过invokeDynamic指令动态生成实现函数式接口的匿名对象,匿名对象重写函数时接口方法中调用使用lambda表达式类中隐式生成的静态私有的方法(该方法就是lambda表达式中的代码内容)

最后(不要白嫖,一键三连求求拉~)

本篇文章笔记以及案例被收入 gitee-StudyJava、 github-StudyJava 感兴趣的同学可以stat下持续关注喔~

有什么问题可以在评论区交流,如果觉得菜菜写的不错,可以点赞、关注、收藏支持一下~

关注菜菜,分享更多干货,公众号:菜菜的后端私房菜

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/403952.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【鸿蒙 HarmonyOS 4.0】ArkTS开发语言

一、背景 ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript&#xff08;简称TS&#xff09;生态基础上做了进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。 二、基本语法 2.1、基本语法介绍 ArkTS的基本组成&#xff0c;资料来自…

查找算法/搜索 | 二分法(python)

Hi&#xff0c;大家好&#xff0c;我是半亩花海。近期在学习算法与数据结构相关知识&#xff0c;纯纯小白&#xff0c;欢迎一起交流呀。打算从算法学起&#xff0c;首先学习查找算法&#xff08;搜索&#xff09;中的二分法&#xff0c;我使用的是 python 语言进行学习。本算法…

【QT-lineEidte动画效果

QT-lineEidte动画效果 一、演示效果二、核心代码三、下载链接 一、演示效果 二、核心代码 #ifndef DynamicUnderlineLineEdit_H #define DynamicUnderlineLineEdit_H#include <QWidget> #include <QLineEdit> #include <QPainter> #include <QPaintEvent…

【学习iOS高质量开发】——协议与分类

文章目录 一、通过委托与数据源协议进行对象间通信1.委托模式2.要点 二、将类的实现代码分散到便于管理的数个分类之中1.如何实现2.要点 三、总是为第三方类的分类名称加前缀1.为什么总是为第三方类的分类名称加前缀2.要点 三、勿在分类中声明属性1.勿在分类中声明属性的原因2.…

【最新Dubbo3深入理解】Dubbo3中的SPI机制以及IOC、AOP

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

MFC 配置Halcon

1.新建一个MFC 工程&#xff0c;Halcon 为64位&#xff0c;所以先将工程改为x64 > VC 目录设置包含目录和库目录 包含目录 库目录 c/c ->常规 链接器 ->常规 > 链接器输入 在窗口中添加头文件 #include "HalconCpp.h" #include "Halcon.h"…

canvas水波纹效果,jquery鼠标水波纹插件

canvas水波纹效果&#xff0c;jquery鼠标水波纹插件 效果展示 jQuery水波纹效果&#xff0c;canvas水波纹插件 HTML代码片段 <div class"scroll04wrap"><h3>发展历程</h3><div class"scroll04"><p>不要回头&#xff0c;一…

移动硬盘误删的文件还能找回来吗?1分钟弄清答案!

“想问问大家如果移动硬盘里保存了很多文件&#xff0c;但上次使用时不小心将部分文件删除了&#xff0c;还有机会找回误删的文件吗&#xff1f;应该怎么进行误删文件的恢复呢&#xff1f;” 在数字化时代&#xff0c;移动硬盘成为了我们存储和传输数据的重要工具。然而&#x…

外泌体相关基因肝癌临床模型预测——2-3分纯生信文章复现——02.数据格式整理(1)

内容如下&#xff1a; 1.外泌体和肝癌TCGA数据下载 2.数据格式整理 3.差异表达基因筛选 4.预后相关外泌体基因确定 5.拷贝数变异及突变图谱 6.外泌体基因功能注释 7.LASSO回归筛选外泌体预后模型 8.预后模型验证 9.预后模型鲁棒性分析 10.独立预后因素分析及与临床的…

【Appium UI自动化】pytest运行常见错误解决办法

通过Appium工具录制代码在pycharm上运行报错&#xff1a; 错误一&#xff1a; 1.提示 setup() 方法运行 error failed 解决办法&#xff1a;未创建 init __ 方法&#xff0c;创建一个空的__init.py文件就解决了。 原因&#xff1a; 错误二&#xff1a; 2.运行代码&#xff…

Rabbitmq入门与应用(四)-RabbitMQ常见模式

RabbitMQ常见Queue模式 简单模式 点对点模式&#xff0c;一个生产者一个消费者 生产者将消息发送到队列&#xff0c;消费者从队列中获取消息&#xff0c;队列是存储消息的缓冲区。 查看管理端效果 序列化解决方案 基于java序列化基于Json Bean public MessageConverter mess…

【Java从入门到精通】Java Character 类

Java Character 类 Character 类用于对单个字符进行操作。 Character 类在对象中包装一个基本类型 char 的值 实例 char ch a;// Unicode 字符表示形式 char uniChar \u039A; // 字符数组 char[] charArray { a, b, c, d, e }; 然而&#xff0c;在实际开发过程中&#xf…

利用Python email的MIMEBase及MIMEApplication发送邮件附件

**MIMEBase、 MIMEApplication背景知识点总结** MIMEBase 和 MIMEApplication 都是用于创建 MIME 消息的类&#xff0c;但它们之间有一些异同点。 异同点如下&#xff1a; 用途&#xff1a; MIMEBase 是一个基类&#xff0c;用于表示任何类型的 MIME 消息部分。它提供了一种通…

Video generation models as world simulators-视频生成模型作为世界模拟器

原文地址&#xff1a;Video generation models as world simulators 我们探索在视频数据上进行大规模生成模型的训练。具体来说&#xff0c;我们联合训练文本条件扩散模型&#xff0c;同时处理不同持续时间、分辨率和长宽比的视频和图像。我们利用一个在视频和图像潜在编码的时…

Redis信创平替之TongRDS(东方通),麒麟系统安装步骤

我的系统: 银河麒麟桌面系统V10(SP1)兆芯版 1.先进入东方通申请使用 2.客服会发送一个TongRDS包与center.lic给你(我这里只拿到.tar.gz文件,没有网上的什么安装版) 3.上传全部文件到目录中 4.服务节点安装,并启动 tar -zxvf TongRDS-2.2.1.2_P3.Node.tar.gz cd pmemdb/bin/…

c++实现栈和队列类

c实现栈和队列类 栈(Stack)Stack示意图Stack.cpp 队列(queue)queue 示意图queue.cpp 栈(Stack) Stack示意图 Stack.cpp #pragma once #include "ListStu.cpp"template<typename T> class Stack { public: /* * void push(T& tDate)* 参数一 &#xff1a;…

【Linux从青铜到王者】 基础IO

本篇重点&#xff1a;文件描述符&#xff0c;重定向&#xff0c;缓冲区&#xff0c;磁盘结构&#xff0c;文件系统&#xff0c;inode理解文件的增删查改&#xff0c;查找一个文件为什么一定要有路径&#xff0c;动静态库&#xff0c;有的时候为什么找不到库&#xff0c;动态库的…

SQL面试题及答案

介绍 在快节奏的数据管理和信息技术世界中,导航和操作结构化数据的能力是一项非常重要的技能。SQL,即结构化查询语言,是关系数据库的基石,掌握这种语言的专业人员的需求量很大。SQL 面试在科技行业很常见,潜在的候选人会接受测试以展示他们的知识和解决问题的能力。为了帮…

酷开科技丨新年新玩法!酷开系统壁纸模式给客厅“换”新

甲辰龙年即将到来&#xff0c;新年新家新气象&#xff0c;快到酷开系统壁纸模式中挑选一款喜欢的壁纸&#xff0c;为新的一年增添一份美好和喜悦吧&#xff01; 酷开科技将更多的电视新玩法带给你&#xff0c;让你的电视成为家庭中的焦点&#xff01;酷开系统壁纸模式&#xf…

【前端素材】推荐优质后台管理系统APP Zina平台模板(附源码)

一、需求分析 当我们从多个层次来详细分析后台管理系统时&#xff0c;可以将其功能和定义进一步细分&#xff0c;以便更好地理解其在不同方面的作用和实际运作。 1. 功能层次 a. 用户管理功能&#xff1a; 用户注册和登录&#xff1a;管理用户账户的注册和登录过程。权限管…