1.語法糖

程序員喜歡將一些複雜的代碼或邏輯寫成幾行,使代碼緊湊和可讀。編程語言的創造者有時會為此提供幫助。

一種可以讓您走捷徑(少寫代碼)的靈活語言功能稱為句法糖。但是,老實說,在 Java 中幾乎沒有。

Java 的創建者竭盡所能消除 Java 中的任何冗餘。如果 C++ 允許您以 20 種方式做某事,那麼 Java 只允許您以一種方式做。

但是 Java 程序員和 Java 的創造者都不喜歡缺乏自由。有時糖會讓像你我這樣的普通人的生活更輕鬆。

順便說一下,您已經遇到了一些語法糖:自動裝箱拆箱。讓我們比較一下:

長碼 代碼緊湊
Integer a = new Integer(5);
int b = a.intValue();
Integer a = 5;
int b = a;
int b = 5;
Integer c = new Integer(b);
int b = 5;
Integer c = b;
Integer a = new Integer(1);
int b = 1;
if (a.intValue() == b)
{
   ...
}
Integer a = 1;
int b = 1;
if (a == b)
{
   ...
}

您可以在右側編寫更緊湊的代碼,而不是左側的長代碼。智能Java 編譯器將根據簡短版本的代碼生成詳細版本的代碼。這正是語法糖。


2.變量類型的推斷:var關鍵字

在 Java 11 中,編譯器變得更加智能,現在可以根據分配給它的值的類型來確定聲明變量的類型。在代碼中,它看起來像這樣:

var name = value;

其中name是新變量的名稱,value是它的初始值,var是用來聲明變量的關鍵字。名稱變量的類型將與分配給它的值的類型相同。

例子:

我們如何看待代碼 編譯器看到了什麼
var i = 1;
int i = 1;
var s = "Hello";
String s = "Hello";
var console = new Scanner(System.in);
Scanner console = new Scanner(System.in);
var list = new ArrayList<String>();
ArrayList<String> list = new ArrayList<String>();
var data = new int[]{1, 2, 3};
int[] data = new int[]{1, 2, 3};

編譯器本身根據分配給它的值來確定或推斷變量的類型。

程序員們就是否要在語言中添加這樣的特性展開了激烈的爭論。許多人擔心它var會被濫用,從而影響代碼的可讀性。

這有一定的道理,所以最好var在它增加代碼可讀性的地方使用。例如,這些在兩種情況下:

Case 1: 看變量賦值,變量類型一目了然

代碼 解釋
var stream = url.getInputStream();
變量是一個InputStream
var name = person.getFullName();
變量是String

在這些情況下,您不應該使用var. 那麼,變量的類型是什麼?

代碼 解釋
var result = task.execute();
很難確定變量的類型
var status = person.getStatus();
很難確定變量的類型

情況 2:變量的類型對於理解代碼並不重要

代碼通常不需要調用變量的方法,例如,當變量僅用於臨時存儲某些內容時。在這種情況下,使用var絕對不會降低代碼的可讀性:

長碼 代碼緊湊
var data = stream.getMetaData();
storage.save(data)
我們從stream流中獲取元數據並將其保存在storage存儲庫中。變量data的特定類型並不重要。

中庸之道

現在我將給出三種編寫相同代碼的方法。使用var將是最好的選擇。

代碼 筆記
dest.writeHeaderInfo(src.getFileMetaInfo());
太緊湊
var headerInfo = src.getFileMetaInfo();
dest.writeHeaderInfo(headerInfo);
正好
FileMetaInfo headerInfo = src.getFileMetaInfo();
dest.writeHeaderInfo(headerInfo);
太詳細了

從 1 行版本轉移到 2 行版本,我們通過使用變量名 ( ) 使代碼更具可讀性headerInfo。現在很明顯,該方法不僅返回元信息,還返回標頭信息。

第三個版本過於冗長。從方法中已經很清楚headerInfois的事實。元信息的用途更有趣。FileMetaInfogetFileMetaInfo()



3.用菱形運算符省略類型:<>

甚至在var運算符出現之前,就有人嘗試教編譯器如何推斷集合類型。你會同意這個符號看起來有點多餘:

ArrayList<String> list = new ArrayList<String>();

從Java第七版開始,在寫集合類型時,如果聲明變量時指定了集合元素的類型,則可以省略。也就是說,上面的代碼可以寫成稍微簡化的形式:

ArrayList<String> list = new ArrayList<>();

如您所見,您不再需要第二次編寫 String。不像 var 運算符那麼酷,但在當時看來是進步了。

集合類型中的空尖括號被稱為菱形運算符,因為兩個尖括號隱約類似於菱形。

同時使用var關鍵字和菱形運算符 是不可取的:

var list = new ArrayList<>();

根本沒有關於集合中存儲的元素類型的信息,集合類型將ArrayList <Object> 。



4.雙花括號

還記得快速數組初始化嗎?

我們只是在大括號中列出了值,如下所示:

例子
int[] data = new int[] {1, 2, 3, 4, 5, 6, 7};
int[] data = {1, 2, 3, 4, 5, 6, 7};

Java 的創造者喜歡使用花括號來簡化數組元素的編寫的想法。但是集合呢?

Java 的創造者對集合也有足夠的創造性思維,允許他們使用雙花括號的技巧。

加糖 不加糖
var list = new ArrayList<String>()
{{
   add("Hello");
   add("How's");
   add("Life?");
}};
var list = new ArrayList<String>();

list.add("Hello");
list.add("How's");
list.add("Life?");

如果編譯器遇到左側示例中的代碼,則會將其轉換為右側的代碼。

代碼並沒有變得更緊湊。這裡的節省是微不足道的:您不必list每次都寫。如果變量名很長,這會很有幫助。

但是,如果您在項目中遇到這樣的代碼,請不要感到驚訝 🙂