点击上方蓝字关注我们
语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家 Peter.J.Landin 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响, 但是更方便程序员使用。
1 自动装箱与拆箱
自动装箱就是 Java 自动将原始类型值转换成对应的对象,比如将 int 的变量转换成 Integer 对象,这个过程叫做装箱,反之将 Integer 对象转换成 int 类型值,这个过程叫做 拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。原 始类型 byte, short, char, int, long, float, double 和 boolean 对应的封装类为 Byte, Short, Character, Integer, Long, Float, Double, Boolean。
从反编译得到内容可以看出,在装箱的时候自动调用的是 Integer 的 valueOf(int)方 法。而在拆箱的时候自动调用的是 Integer 的 intValue 方法。所以,装箱过程是通过调用包装器的 valueOf 方法实现的,而拆箱过程是通过调用包 装器的 xxxValue 方法实现的。
2 for-each
增强 for 循环(for-each)相信大家都不陌生,日常开发经常会用到的,他会比 for 循环要少写很多代码,那么这个语法糖背后是如何实现的呢?
代码很简单,for-each 的实现原理其实就是使用了普通的 for 循环和迭代器。
3 try-with-resource
Java 里,对于文件操作 IO 流、数据库连接等开销非常昂贵的资源,用完之后必须及 时通过 close 方法将其关闭,否则资源会一直处于打开状态,可能会导致内存泄露等问题。关闭资源的常用方式就是在 finally 块里是释放,即调用 close 方法。比如,我们经常会写这样的代码:
从 Java 7 开始,jdk 提供了一种更好的方式关闭资源,使用 try-with-resources 语 句,改写一下上面的代码,效果如下:
这简直是一大福音啊,虽然我之前一般使用 IOUtils 去关闭流,并不会使用在 finally 中写很多代码的方式,但是这种新的语法糖看上去好像优雅很多呢。看下他的背后:其实背后的原理也很简单,那些我们没有做的关闭资源的操作,编译器都帮我们做了。所以,再次印证了,语法糖的作用就是方便程序员的使用,但最终还是要转成编译器认识的语言。
4 Lambda 表达式
关于 lambda 表达式,有人可能会有质疑,因为网上有人说他并不是语法糖。其实我 想纠正下这个说法。Labmda 表达式不是匿名内部类的语法糖,但是他也是一个语法糖。实现方式其实是依赖了几个 JVM 底层提供的 lambda 相关 api。先来看一个简单的 lambda 表达式。遍历一个 list:
可以看到,在 forEach 方法中,其实是调用了 java.lang.invoke.LambdaMetafact ory#metafactory 方法,该方法的第四个参数 implMethod 指定了方法实现。可以看到这 里其实是调用了一个 lambda$main$0 方法进行了输出。
再来看一个稍微复杂一点的,先对 List 进行过滤,然后再输出:两个 lambda 表达式分别调用了 lambda$main$1 和 lambda$main$0 两个方法。所以,lambda 表达式的实现其实是依赖了一些底层的 api,在编译阶段,编译器会把 lambda 表达式进行解糖,转换成调用内部 api 的方式。
5 内部类
内部类又称为嵌套类,可以把内部类理解为外部类的一个普通成员。内部类之所以也是语法糖,是因为它仅仅是一个编译时的概念,outer.java 里面定义 了一个内部类 inner,一旦编译成功,就会生成两个完全不同的.class 文件了,分别是 outer.class 和 outer$inner.class。所以内部类的名字完全可以和它的外部类名字相同。以上代码编译后会生成两个 class 文件:OutterClass$InnerClass.class 、Outter Class.class 。当我们尝试对 OutterClass.class 文件进行反编译的时候,命令行会打印 以下内容:Parsing OutterClass.class...Parsing inner class OutterClass$InnerCl ass.class... Generating OutterClass.jad 。他会把两个文件全部进行反编译,然后一 起生成一个 OutterClass.jad 文件。文件内容如下:
6 总结
所谓语法糖就是提供给开发人员便于开发的 一种语法而已。但是这种语法只有开发人员认识。要想被执行,需要进行解糖,即转成 JVM 认识的语法。当我们把语法糖解糖之后,你就会发现其实我们日常使用的这些方便的 语法,其实都是一些其他更简单的语法构成的。有了这些语法糖,我们在日常开发的时候可以大大提升效率,但是同时也要避免过渡使 用。使用之前最好了解下原理,避免掉坑。
还有什么其他Java语法糖?欢迎评论交流~