漫話:如何給女朋友解釋什么是語法糖?









語法糖(Syntactic sugar),也譯為糖衣語法,是由英國計算機科學(xué)家Peter J. Landin發(fā)明的一個技術(shù)術(shù)語,指在計算機語言中添加的某種語法,這種語法對語言的功能并沒有影響,但是更方便程序員使用。
類比一下就像我們?nèi)粘J褂玫囊恍┛s寫、別稱或者是"黑話"、"暗語"等。都是用一種更加簡練的語言表達復(fù)雜的含義。
如我們有人說"基操勿6",直意為“不要大驚小怪,這只是基本操作”,表現(xiàn)一種低調(diào)的得意。
當(dāng)我們形容一個妹子的時候可以說她是"可鹽可甜"等等的。

通過使用這些暗語、黑話,可以起到很多作用,如更加簡潔、更加自然、效率高、錯誤少等。
而在編程語言中引入語法糖,在使用上同樣可以起到使代碼更加簡潔、提升代碼可讀性、提升編程效率、降低程序出現(xiàn)錯誤的概率等。
有了暗語、黑話,可以讓人們交流更加順暢,有了語法糖,可以讓程序員寫代碼更加爽。是一個道理。




就像我們?nèi)粘Uf的一些"暗語"、"黑話",這些被發(fā)明出來是方便人們使用的,但是并不是所有人都能看得懂。
在看得懂的人之間使用的話是很方便的,但是如果有人不懂的話,就需要解釋給他們聽。
同理,語法糖是編程語言中增加的一些語法特性,目的是方便開發(fā)人員的使用,拿Java語言舉例,雖然Java中有很多語法糖,但是Java虛擬機并不支持這些語法糖,所以這些語法糖在編譯階段就會被還原成簡單的基礎(chǔ)語法結(jié)構(gòu),這樣才能被虛擬機識別,這個過程就是解語法糖。
如果看過Java虛擬機的源碼,就會發(fā)現(xiàn)在編譯過程中有一個重要的步驟就是調(diào)用desugar(),這個方法就是負責(zé)解語法糖的實現(xiàn)。
通常情況下,我們可以通過反編譯(漫話:如何給女朋友解釋什么是編譯與反編譯)的方式學(xué)習(xí)語法糖具體是如何實現(xiàn)的。




Java作為一種高級語言,是有很多語法糖的,而且從Java 7開始,幾個重要的版本中提供的新特性都是和語法糖有關(guān)系的。
逐漸的,Java已經(jīng)從一個低糖語言變成一個高糖語言了。
如switch支持枚舉及字符串、泛型、條件編譯、斷言、可變參數(shù)、自動裝箱/拆箱、枚舉、內(nèi)部類、增強for循環(huán)、try-with-resources語句、lambda表達式等。
還有JDK 10中的局部變量類型推斷、JDK 13中的文本塊(Text Blocks),其實本質(zhì)上都是語法糖。
關(guān)于Java中的語法糖,Hollis大神寫過很多文章深入的介紹過他們的原理,如《不了解這12個語法糖,別說你會Java》、《我反編譯了Java 10的本地變量類型推斷》等。
摘取一段關(guān)于switch對String的支持的分析過程如下:
Java中的swith自身原本就支持基本類型。比如int、char等。對于int類型,直接進行數(shù)值的比較。對于char類型則是比較其ascii碼。
所以,對于編譯器來說,switch中其實只能使用整型,任何類型的比較都要轉(zhuǎn)換成整型。比如byte。short,char(ackii碼是整型)以及int。
看下switch對String得支持,有以下代碼:
public?class?switchDemoString?{
????public?static?void?main(String[]?args)?{
????????String?str?=?"world";
????????switch?(str)?{
????????case?"hello":
????????????System.out.println("hello");
????????????break;
????????case?"world":
????????????System.out.println("world");
????????????break;
????????default:
????????????break;
????????}
????}
}
反編譯后內(nèi)容如下:
public?class?switchDemoString
{
????public?switchDemoString()
????{
????}
????public?static?void?main(String?args[])
????{
????????String?str?=?"world";
????????String?s;
????????switch((s?=?str).hashCode())
????????{
????????default:
????????????break;
????????case?99162322:
????????????if(s.equals("hello"))
????????????????System.out.println("hello");
????????????break;
????????case?113318802:
????????????if(s.equals("world"))
????????????????System.out.println("world");
????????????break;
????????}
????}
}
看到邊以后的代碼,我們就能發(fā)現(xiàn):字符串的switch是通過equals()和hashCode()方法來實現(xiàn)的。
其他語法糖就不在這里詳細介紹了,感興趣的可以到H大的文章中學(xué)習(xí)下,總之學(xué)習(xí)思路都很類似,就是通過反編譯的方式了解解糖后的代碼或者字節(jié)碼是怎樣的。




