前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么是语法糖,如何解糖?

什么是语法糖,如何解糖?

作者头像
博文视点Broadview
发布2022-08-29 18:41:36
9440
发布2022-08-29 18:41:36
举报
文章被收录于专栏:博文视点Broadview

👆点击“博文视点Broadview”,获取更多书讯

语法糖(Syntactic Sugar)也称糖衣语法,是由英国计算机学家Peter.J.Landin发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但更方便程序员使用。

简而言之,语法糖让程序更加简洁,有更高的可读性。

有意思的是,在编程领域,除了语法糖,还有语法盐和语法糖精的说法,篇幅有限,这里不做扩展了。

我们所熟知的编程语言中几乎都有语法糖。

很多人说Java是一个“低糖语言”,其实从Java 7开始。Java在语言层面上一直在添加各种“糖”,主要是在“Project Coin”项目下研发,未来还会持续向着“高糖”的方向发展。

《深入理解Java核心技术》一书中介绍过的Switch对String的支持、泛型、自动拆装箱、枚举、for-each等其实都是语法糖,在介绍相关知识时,我们为了讲解原理,对这些语法糖做了解语法糖(简称解糖)操作。

那么,什么是解糖呢?

01

解语法糖

前面提到,语法糖的存在主要是方便开发人员使用。其实,Java虚拟机并不支持这些语法糖。这些语法糖在编译阶段就会被还原成简单的基础语法结构,这个过程就是解语法糖。

在Java中,javac命令可以将后缀名为.java的源文件编译为后缀名为.class的可以运行于Java虚拟机中的字节码。

如果查看com.sun.tools.javac.main.JavaCompiler的源码,就会发现在compile()中有一个步骤就是调用desugar(),这个方法就是负责解语法糖的。

想要学习Java中的语法糖,必备的一项技能就是对Class文件进行反编译。

02

反编译

因为JVM在编译过程中,会把语法糖解糖,还原成基本语法结构。所以如果我们知道一个语法糖被JVM解糖之后的代码是什么样的,那么就知道了这个语法糖的实现方式。

编译后的Class文件是二进制文件,如何变成程序员可以看得懂的文件呢?这就需要反编译了。

我们可以通过编译器,把高级语言的源代码编译成低级语言,反之,可以通过低级语言进行反向工程,获取其源代码,这个过程就叫作反编译。

虽然很难将机器语言反编译成源代码,但我们可以把中间代码进行反编译。就像我们虽然不能把经过虚拟机编译后的机器语言进行反编译,但我们把javac编译得到的Class文件进行反编译还是可行的。

所以,一般说Java的反编译,就是指将Class文件转换成Java文件。

Java中有很多反编译工具,下面简单介绍几种。

  • javap

javap是JDK自带的一个工具,可以对代码进行反编译,也可以查看Java编译器生成的字节码。javap生成的文件并不是Java文件,而是程序员可以看得懂的Class字节码文件。

  • jad

jad是一个比较不错的反编译工具,只要下载一个执行工具,就可以实现对Class文件的反编译了。

jad可以把Class文件反编译成Java文件。

但是,jad已经很久不更新了,在对Java 7生成的字节码进行反编译时,偶尔会出现不支持的问题,在对Java 8的Lambda表达式反编译时就会彻底失败。

  • CFR

相比jad来说,CFR的语法可能会稍微复杂一些。

  • JD-GUI

JD-GUI是一个独立的图形实用程序,可以显示Class文件的Java源代码。可以使用JD-GUI浏览重建的源代码,以便立即访问方法和字段。

本章后面介绍的所有解糖都是基于反编译来查看源码的,用到的工具主要是jad、CFR和javap。

03

解糖示例:方法变长参数

可变参数(Variable Arguments)是在Java 1.5中引入的一个特性,它允许一个方法把任意数量的值作为参数。

下面是可变参数的代码,其中print方法接收可变参数:

代码语言:javascript
复制
public static void main(String[] args){print("Holis", " 公众号:Hollis", " 博客:www.hollischuang.com", "QQ:907607222");}public static void print(String... strs){for (int i = 0; i < strs.length; i++){System.out.println(strs[i]);}}

反编译后的代码如下:

代码语言:javascript
复制
public static void main(String args[]){print(new String[] {"Holis", "\u516C\u4F17\u53F7:Hollis", "\u535A\u5BA2\uFF1Awww.hollischuang.com", "QQ\uFF1A907607222"});}public static transient void print(String strs[]){for(int i = 0; i < strs.length; i++)System.out.println(strs[i]);}

从反编译后的代码可以看出,在使用可变参数时,首先会创建一个数组,数组的长度就是调用入参作为可变参数的方法时传递的实参的个数,然后把参数值全部放到这个数组中,再把这个数组作为参数传递到被调用的方法中。

内容摘自《深入理解Java核心技术:写给Java工程师的干货笔记(基础篇)》,作者是Hollis(张洪亮):阿里巴巴技术专家,51CTO 专栏作家,CSDN 博客专家,掘金优秀作者,《程序员的三门课》联合作者,《Java工程师成神之路》系列文章作者;热衷于分享计算机编程相关技术,博文全网阅读量数千万。

▊《深入理解Java核心技术:写给Java工程师的干货笔记(基础篇)》

张洪亮(@Hollis)  著

  • 全网阅读量千万的Java工程师成神之路学习笔记,Java基础知识点查漏补缺,随书附赠一份惊喜彩蛋

本书是《Java工程师成神之路》系列的第一本,主要聚焦于Java开发者必备的Java核心基础知识。全书共23章,主要内容包括面向对象、基础数据类型、自动拆装箱、字符串、集合类、反射、序列化、枚举、I/O、动态代理、注解、泛型、时间处理、编码方式、语法糖、BigDecimal、常用工具库及Java新版本特性等,比较全面地覆盖了Java开发者日常工作中用到的大部分基础知识。

“有道无术,术尚可求,有术无道,止于术”。本系列更加注重对Java之“道”的学习,即对原理的解读。对于很多语法概念及使用方式的介绍并不是本书的重点。所以,有一定编程语言常识或者写过Java代码的读者阅读起来会更加容易。

本书既适合读者进行体系化的学习,也适合读者查缺补漏,将以往所学的知识点连成线,进而构建并完善自己的知识体系。

(京东满100减50,快快扫码抢购吧!)

发布:刘恩惠

审核:陈歆懿

代码语言:javascript
复制
如果喜欢本文欢迎 在看丨留言丨分享至朋友圈 三连
 热文推荐  
入门机器学习?还是先抢救一下数学吧!
了解“预训练-微调”,看这一篇就够了
使用Go语言批量同步微信读书笔记到Flomo
管理者数据能力4M 模型

▼点击阅读原文,了解本书详情~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 博文视点Broadview 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 解语法糖
  • 反编译
  • 解糖示例:方法变长参数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档