Java语法糖,快看看你吃过几颗

ed2ccf1e915989c03f58c4de6db093ba.png

点击上方蓝字关注我们

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

 1   自动装箱与拆箱

33601d4ccce96709f845599a2bb71752.png

3384bdb3646b68805b0cdc2d8ef96c99.png

自动装箱就是 Java 自动将原始类型值转换成对应的对象,比如将 int 的变量转换成 Integer 对象,这个过程叫做装箱,反之将 Integer 对象转换成 int 类型值,这个过程叫做 拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。原 始类型 byte, short, char, int, long, float, double 和 boolean 对应的封装类为 Byte, Short, Character, Integer, Long, Float, Double, Boolean。

4ea295c8a86311bc311b199da6ff321c.png

a57b60077a421692ae8cd96979b41fbc.png

从反编译得到内容可以看出,在装箱的时候自动调用的是 Integer 的 valueOf(int)方 法。而在拆箱的时候自动调用的是 Integer 的 intValue 方法。所以,装箱过程是通过调用包装器的 valueOf 方法实现的,而拆箱过程是通过调用包 装器的 xxxValue 方法实现的。

a17ab0a3f78df5e79d3f68735c640431.png

fd16afa819a849e74376b270bbfdc2ec.png

329b404680e7133ca3b009cdd0bb1017.png

 2   for-each

20fa572703f6a04ae7af7d2b0eeb1d0a.png

530bbaa6a7b0693cea9659cc20c73309.png

增强 for 循环(for-each)相信大家都不陌生,日常开发经常会用到的,他会比 for 循环要少写很多代码,那么这个语法糖背后是如何实现的呢?

0d53e16b3d3e5855e9955e2acbd946b1.png

代码很简单,for-each 的实现原理其实就是使用了普通的 for 循环和迭代器。

6fe78591baeea2c1d95442fcd2a187eb.png

4d13ba25a2bdcc0538fa076a84bca5c8.png

210791cc2cb3c93dc682b79b6fbfbf40.png

 3   try-with-resource

fe0320da86f8c8ee9bc521328937bcc9.png

3d58b6da6c091d8cdc1ecdeb3af9a784.png

Java 里,对于文件操作 IO 流、数据库连接等开销非常昂贵的资源,用完之后必须及 时通过 close 方法将其关闭,否则资源会一直处于打开状态,可能会导致内存泄露等问题。关闭资源的常用方式就是在 finally 块里是释放,即调用 close 方法。比如,我们经常会写这样的代码:

9a7e8e95677175f877b8984547ab56a1.png

从 Java 7 开始,jdk 提供了一种更好的方式关闭资源,使用 try-with-resources 语 句,改写一下上面的代码,效果如下:

5497b090a510449aa35af6a5b5556104.png

这简直是一大福音啊,虽然我之前一般使用 IOUtils 去关闭流,并不会使用在 finally 中写很多代码的方式,但是这种新的语法糖看上去好像优雅很多呢。看下他的背后:71bc27132ff0eccfabc60f3f5c445ddb.png其实背后的原理也很简单,那些我们没有做的关闭资源的操作,编译器都帮我们做了。所以,再次印证了,语法糖的作用就是方便程序员的使用,但最终还是要转成编译器认识的语言。

7f64bfee9141a6610de7886a179c420d.png

54d8fa304eb299a4fe77242ce56e5266.png

c73bba539de5173721df38355cafa083.png

 4   Lambda 表达式

ff1ff75a45c58e1dccd8acaaa1e6d1b1.png

1924044a70f0c4e3a8c033259d4ad0aa.png

关于 lambda 表达式,有人可能会有质疑,因为网上有人说他并不是语法糖。其实我 想纠正下这个说法。Labmda 表达式不是匿名内部类的语法糖,但是他也是一个语法糖。实现方式其实是依赖了几个 JVM 底层提供的 lambda 相关 api。先来看一个简单的 lambda 表达式。遍历一个 list:

89bdd4394b9bcc429d282b1897fb08a3.png

d1717a3ec91037dc75181ac70f8f879e.png

可以看到,在 forEach 方法中,其实是调用了 java.lang.invoke.LambdaMetafact ory#metafactory 方法,该方法的第四个参数 implMethod 指定了方法实现。可以看到这 里其实是调用了一个 lambda$main$0 方法进行了输出。

再来看一个稍微复杂一点的,先对 List 进行过滤,然后再输出:6c7ba85034a23dcafcd0f6721dc8daf2.png两个 lambda 表达式分别调用了 lambda$main$1 和 lambda$main$0 两个方法。所以,lambda 表达式的实现其实是依赖了一些底层的 api,在编译阶段,编译器会把 lambda 表达式进行解糖,转换成调用内部 api 的方式。

b52047e0823b0a3f80fb5387665885d7.png

307ba90a58dbfc07f4999a46810c702c.png

d79873198e977255405daf6519b8ce32.png

 5   内部类

3251220a57fa8ad311e4d78ea15b1bef.png

2593689f3592b1c65ecf72e648603711.png

内部类又称为嵌套类,可以把内部类理解为外部类的一个普通成员。内部类之所以也是语法糖,是因为它仅仅是一个编译时的概念,outer.java 里面定义 了一个内部类 inner,一旦编译成功,就会生成两个完全不同的.class 文件了,分别是 outer.class 和 outer$inner.class。所以内部类的名字完全可以和它的外部类名字相同。5e6068c464dbb2b0f68a6ec633fb12c3.png7f8a16fd47b4a9bd3a3921c8dc46c20e.png以上代码编译后会生成两个 class 文件:OutterClass$InnerClass.class 、Outter Class.class 。当我们尝试对 OutterClass.class 文件进行反编译的时候,命令行会打印 以下内容:Parsing OutterClass.class...Parsing inner class OutterClass$InnerCl ass.class... Generating OutterClass.jad 。他会把两个文件全部进行反编译,然后一 起生成一个 OutterClass.jad 文件。文件内容如下:

266c2962a33e9cd15926c250c8ddd0f0.png

ff7f37fa22b4669c0150830dbea94795.png

39e65da47946d18a03d47fd255d147b3.png

8f3f1a212e486ba0d9cda29eca35630f.png

 6  总结

640127c59d091d2f0d6693b955ebaf5d.png

62bbdb5673c2657adcf206779b8de654.png

所谓语法糖就是提供给开发人员便于开发的 一种语法而已。但是这种语法只有开发人员认识。要想被执行,需要进行解糖,即转成 JVM 认识的语法。当我们把语法糖解糖之后,你就会发现其实我们日常使用的这些方便的 语法,其实都是一些其他更简单的语法构成的。有了这些语法糖,我们在日常开发的时候可以大大提升效率,但是同时也要避免过渡使 用。使用之前最好了解下原理,避免掉坑。

64611b891893887338ecb449ba15d58c.png

953b104a1c02cc000671e2f996eadd74.png

97e968e0b6902743797698a7a32678e7.png

还有什么其他Java语法糖?欢迎评论交流~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值