前言
今天继续温故知新java语言中的关键词:语法糖

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

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

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

解糖
语法糖的存在主要是方便开发人员使用,Java虚拟机并不支持这些语法糖。这些语法糖在编译阶段就会被还原成简单的基础语法结构,这个过程就是解语法糖
JVM在编译过程中,会把语法糖解糖,还原成基本语法结构,所以如果要分析java语言中如何进行加糖和解糖的,要通过分析Class文件

反编译class文件工具:javap、jad、CFR、JD-GUI

分析示例

1、方法变长参数

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

package com.sk.init;

public class Test02 {

    public static void main(String[] args) {
        test("赵四","刘能","汪老师");
    }

    public static void test(String... strs){
        for (int i = 0; i < strs.length; i++) {
            System.out.println(strs[i]);
        }
    }

}

反编译后:

import com.sk.init.Test02;

public class Test02 {
  public static void main(String[] args) {
    test(new String[] { ", ", "});
  }
  
  public static void test(String... strs) {
    for (int i = 0; i < strs.length; i++)
      System.out.println(strs[i]); 
  }
}

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

2、String类型
String类型拼接字符串

示例代码:

package com.sk.init;

public class Test03 {

    public static void main(String[] args) {

        String a = "赵四";
        String b = "刘能";
        String c = a + b;

    }

}

反编译代码:

package com.sk.init;

public class Test03 {
    public Test03() {
    }

    public static void main(String[] args) {
        String a = "赵四";
        String b = "刘能";
        (new StringBuilder()).append(a).append(b).toString();
    }
}

String拼接操作是重新创建了一个StringBuilder对象

3、Integer装箱和拆箱

我们知道,java中Integer类型对于-128-127之间的数是缓冲区取的,所以用等号比较是一致的。
但对于不在这区间的数字是在堆中new出来的对象。所以地址空间不一样,也就不相等。

代码示例:

package com.sk.init;

public class Test05 {

    public static void main(final String[] args) {
        final Integer a = 500;
        final Integer b = 500;
        final Integer c = 100;
        final Integer d = 100;
        System.out.println("a=b   :" + (a == b));
        System.out.println("c=d   :" + (c == d));
    }

}

执行结果:

a=b   :false
c=d   :true