天天看點

Java新特性:資料類型可以扔掉了?

Java新特性:資料類型可以扔掉了?

在很久很久以前,我們寫代碼時要慎重的考慮變量的資料類型,比如下面這些:

Java新特性:資料類型可以扔掉了?
枚舉:盡管在 JDK 5 中增加了枚舉類型,但是 Class 檔案常量池的 CONSTANT_Class_info 類型常量并沒有發生任何語義變化,仍然是代表一個類或接口的符号引用,沒有加入枚舉,也沒有增加過“CONSTANT_Enum_info”之類的“枚舉符号引用”常量。是以使用 enum 關鍵字定義常量,盡管從 Java 文法上看起來與使用 class 關鍵字定義類、使用 interface 關鍵字定義接口是同一層次的,但實際上這是由 Javac 編譯器做出來的假象,從位元組碼的角度來看,枚舉僅僅是一個繼承于 java.lang.Enum、自動生成了 values() 和 valueOf() 方法的普通 Java 類而已,是以枚舉也歸為引用類型了。

然而到了 JDK 10 時,我們就有了新的選擇,JDK 10 中新增了 var 局部變量推斷的功能,使用它我們可以很 happy 的忘記資料類型這件事了,那它是如何使用的呢?接下來我們一起來看。

接下來我們就使用對比的方式,來體會一下 var 的作用。

舊寫法:

新寫法:

PS:這裡的舊寫法指的是 JDK 10 之前的版本,而新寫法指的是 JDK 10 以後(包含 JDK 10)的版本。
PS:當遇到不同類型相加時(int+ double)會發生資料類型向上轉型,是以 num3 就會更新為 double 類型。

通過上面的示例我們可以看出, var 具備兩個明顯的優點:提高了代碼的可讀性和命名對齊。

我們在沒有使用 var 之前,如果類型的名稱很長就會出現下面的這種情況:

當限定每行不能超過 150 個字元的話,變量名就會被推到下一行顯示,這樣整個代碼的可讀性就變得很低。但當我們使用了 var 之後,代碼就變成了這樣:

從上述的代碼可以看出,當類型越長時,var(可讀性)的價值就越大。

在不使用 var 時,當遇到下面這種情況,代碼就是這樣的:

在使用了 var 之後,代碼是這樣的:

從上述代碼可以看出使用了 var 之後,命名對齊了,整個代碼也變得更優雅了。

var 的實作來自于 JEP 286 (改善提議 286),詳情位址 :http://openjdk.java.net/jeps/286

從 JEP 286 的标題“局部變量類型推斷”可以看出,var 隻能用于局部變量聲明,也就是說 var 必須滿足以下條件:

它隻能用于局部變量上;

聲明時必須初始化;

不能用作方法參數和全局變量(類變量)。

PS:因為 var 的實作必須根據等會右邊的代碼進行類型推斷,是以它不能被指派 null 或不被初始化。
Java新特性:資料類型可以扔掉了?
Java新特性:資料類型可以扔掉了?
Java新特性:資料類型可以扔掉了?
Java新特性:資料類型可以扔掉了?
Java新特性:資料類型可以扔掉了?

經過前面的使用我們對 var 已經有了初步的認識,但 var 的實作原理是什麼呢?

為了搞清楚它的原理,我們對下面的代碼進行了編譯(使用指令 javac MainTest.java):

Java新特性:資料類型可以扔掉了?

然後我們再用反編譯工具打開被編譯的類發現:var 竟然被替換成一個個确定的資料類型了,如下圖所示:

Java新特性:資料類型可以扔掉了?

由此我們可以得出結論:var 關鍵字的實作和它的名字密切相關, var 隻是局部類型推斷,它隻會在 Java 編碼期和編譯期有效,當類被編譯為 class 檔案時,var 就會變成一個個确定的資料類型(通過推斷得出)。 是以我們可以把 var 通俗的了解為 Java 的文法糖,使用它可以讓我們快速優雅的實作業務代碼,但 var 在位元組碼層面是不存在的。

本文我們介紹了 var(局部類型推斷)的使用,它可以用在局部變量、 for、 Lambda 的變量聲明中,但不能用在全局變量的聲明中,也不能用它作為方法的傳回值,并且在聲明時一定要進行初始化(也不能指派為 null)。使用 var 可以有效的提高代碼的可讀性和命名對齊,它的實作原理,是在編譯期通過等号右側的代碼進行類型推斷,然後再将 var 替換成确定的資料類型。