語法糖(Syntactic sugar),也譯為糖衣語法,是由英國計算機科學家彼得·蘭丁發(fā)明的一個術(shù)語,指計算機語言中添加的某種語法,這種語法對語言的功能并沒有影響,但是更方便程序員使用。語法糖讓程序更加簡潔,有更高的可讀性。? ? ? ----維基百科
Java中有很多語法糖,使用時很方便,可以提高編程效率,下面通過代碼來說明。
語法糖一: "+"
字符串可以通過"+"號拼接,那么實際上編譯器是怎么處理呢。
for(inti=0;i<10;i++){
String a= i+"a";
}
使用javac編譯成class文件,然后使用CFR反編譯class文件,用--stringbuilder false控制進行解語法糖

打開生成的Java文件,發(fā)現(xiàn)原代碼段變成一下內(nèi)容
for(inti =0;i <10;++i) {
String string =newStringBuilder().append(i).append("a").toString();
}
可以發(fā)現(xiàn),原本的"+"號不見了,替換為StringBuilder,利用其功能進行字符串拼接,因此,"+"號是Java中的一個語法糖,在編程過程中,寫"+"總比寫StringBuilder更加方便,這就是語法糖的意義
語法糖二: switch中使用String
原代碼
switch (s) {
default:
System.out.println("Test");
break;
case "BB":
return 12;
case "Aa":
case "FRED":
return 13;
}
然后同樣利用CFR進行反編譯,得出如下內(nèi)容:
unnamed_local_s_2 = s;
unnamed_local_s_3 = -1;
switch (unnamed_local_s_2.hashCode()) {
case 2112: {
if (unnamed_local_s_2.equals("Aa")) {
unnamed_local_s_3 = 2;
break;
}
if (!(unnamed_local_s_2.equals("BB"))) break;
unnamed_local_s_3 = 1;
break;
}
case 2166379: {
if (!(unnamed_local_s_2.equals("FRED"))) break;
unnamed_local_s_3 = 3;
}
}
switch (unnamed_local_s_3) {
default: {
System.out.println("Test");
break;
}
case 1: {
return 12;
}
case 2: case 3: {
return 13;
}
}
這代碼就膨脹得很厲害了(分成一段段我覺得這是編輯器的問題),可以看到Switch中使用String,編譯器對其處理比較復雜,在代碼層面上,編譯器對開發(fā)人員屏蔽了復雜的實現(xiàn)細節(jié)。
語法糖三: Finally
在寫一些有關(guān)IO功能的代碼時,一般會這樣
try...catch...finally{
//一定要執(zhí)行的內(nèi)容,放掉占用的資源
}
那么如何保證finally中的代碼在各種執(zhí)行分支中一定被執(zhí)行到呢,
寫代碼實驗:
try {
if (x == 0) {
System.out.println("0");
return;
}
if (x < 10) {
System.out.println("10");
return;
}
if (x < 100) {
System.out.println("100");
return;
}
if (x < 1000) {
System.out.println("1000");
return;
}
} catch (Exception e) {
System.out.println("Exception");
} finally {
System.out.println("HERE");
}
編譯成class文件,同樣利用CFR反編譯,加上--decodefinally false,得到代碼大概這樣子:
block10 : {
block9 : {
block8 : {
if (n != 0) break block8;
System.out.println("0");
System.out.println("HERE");
return;
}
if (n >= 10) break block9;
System.out.println("10");
System.out.println("HERE");
return;
}
if (n >= 100) break block10;
System.out.println("100");
System.out.println("HERE");
return;
}
try {
if (n < 1000) {
System.out.println("1000");
System.out.println("HERE");
return;
}
System.out.println("HERE");
}
catch (Exception var2_2) {
try {
System.out.println("Exception");
System.out.println("HERE");
}
catch (Throwable var3_3) {
System.out.println("HERE");
throw var3_3;
}
}
很容易看出,編譯器對finally的處理簡單粗暴,直接在每個執(zhí)行分支最后加上finally里面的代碼,因此,finally的代碼無論前面執(zhí)行哪個分支,最后都會執(zhí)行它。
語法糖四: Enums
曾經(jīng)聽說Android中為了提高性能,建議盡量不使用Enums,這是什么原因?
寫代碼測試:
public enum EnumTest1 {
FOO,
BAR,
BAP
}
代碼很簡單,同樣編譯反編譯,結(jié)果為:
class EnumTest1
extends Enum
{
// Fields
public static final /* enum */ EnumTest1 FOO;
public static final /* enum */ EnumTest1 BAR;
public static final /* enum */ EnumTest1 BAP;
private static final /* synthetic */ EnumTest1[] $VALUES;
// Methods
public static EnumTest1[] values()
{
return EnumTest1.$VALUES.clone();
}
public static EnumTest1 valueOf(String name)
{
return Enum.valueOf(org/benf/cfr/tests/EnumTest1, name);
}
private EnumTest1(String unnamed_local_this_1, int unnamed_local_this_2)
{
super(unnamed_local_this_1, unnamed_local_this_2);
}
static void ()
{
EnumTest1.FOO = new EnumTest1("FOO", 0);
EnumTest1.BAR = new EnumTest1("BAR", 1);
EnumTest1.BAP = new EnumTest1("BAP", 2);
EnumTest1.$VALUES = new EnumTest1[]{EnumTest1.FOO, EnumTest1.BAR, EnumTest1.BAP};
}
}
可以看出,enum被編譯成了一個類,利用原來類的特性來實現(xiàn)enum的功能,因此寫一個enum等于寫一個類,有人建議使用常量之類的來代替enum,因為它太"重"了,但是,現(xiàn)在的手機的性能對于增加一個類其實也沒什么性能的問題。
總結(jié)
除了上面四種語法糖,Java還有很多,例如foreach等等,語法糖給編程帶來了很多方便,提高效率,復雜的邏輯都有編譯器邦我們處理了。