區域變數型別推斷是有爭議的熱點,但 Java 10 在 JVM 中的垃圾收集和容器識別上帶來了可喜的變化,
關于本系列
所以你認為你了解 Java 編程? 事實是,大多數開發人員只是浮于 Java 平臺的表面上,僅僅為了完成作業而學習,在這個正在進行的系列中,Java 技術深入挖掘了 Java 平臺的核心功能,提出了一些技巧和訣竅,可以幫助你解決即使是最棘手的編程挑戰,
Java? 開發人員已經習慣了等待新的 Java 版本發布,但是新的、高頻率的發布節奏改變了這一情況,Java 9 出現之后僅僅過去 6 個月,現在 Java 10 已經在敲門了,再過 6 個月,我們將迎來 Java 11,一些開發人員可能會發現這樣的快速發布是多余的,但是新的節奏標志著一個長期需求的改變,
與它的版本號一樣,Java 10 提供了 10 個新特性,本文提供了我認為最重要的 5 個特性(您可以在 Open JDK 10 專案頁面上查看它們),
Java的新版本節奏
從歷史上看,JDK 發行的節奏是由大的新特性驅動的,作為最近的例子,Java 8 以 lambda 和流的形式引入了函式式編程,而 Java 9 引入了模塊化 Java 系統,每個新版本都被熱切地期待著,但是次要的修復程式經常束之高閣,等待更大的組件版本被最終確定,Java 的進化落后于其他語言,
新的高頻節奏將 Java 以更小的增量向前推進,在發布日期準備好的特性將被包括在內,而那些不能被安排在下一個版本中,就在 6 個月之后,在這個新周期下的第一個 Java 版本是 Java 9,它于 2017 年 10 月發布,Java 10 于 2018 年 3 月發布,Java 11 將于 2018 年 9 月發布,
作為新節奏的一部分,甲骨文表示,它將只支持每個主要版本,直到下一個主要版本發布為止, 當 Java 11 發布時,Oracle 將停止支持 Java 10,支持 Java 版本的開發人員必須每 6 個月遷移一次主要版本, 不希望或不需要頻繁遷移的開發人員可以使用 LTS(長期支持)版本,該版本每三年更新一次, 目前的 LTS 版本 Java 8 將在今年秋季發布 Java 11 之前得到支持,
區域變數型別推斷
區域變數型別推斷是 Java 10 中最顯著的特性,在進入 JDK 10 之前,爭論非常激烈,該特性允許編譯器推斷區域變數的型別,而不是要求程式員明確指定它,
清單 1 顯示了如何在 Java 10 之前定義一個String變數型別,
清單 1. 宣告并分配一個 String 型別的變數
String name = "Alex"
清單 2 展示了在 Java10 中定義與 String 型別相同的變數
清單 2. 用區域變數型別推斷 String 型別的變數
var name = "Alex";
正如你看到的,唯一的區別就是使用了 var 保留型別名稱,使用右邊的運算式,編譯器可以將變數名的型別推斷為 String,
這看起來有點簡單,讓我們來看一個更加復雜的例子,如果一個變數分配給了呼叫方法的回傳值是怎樣的?在這種情況下,編譯器可以根據方法的回傳型別推斷變數的型別,如清單 3 所示,
清單 3. 從回傳型別推斷 String 型別
var name = getName();
String getName(){
return "Alex";
}
使用區域變數型別
顧名思義,區域變數型別推斷功能僅適用于區域變數, 它不能用于定義實體或類變數,也不能用于方法引數或回傳型別, 但是,您可以在類和增強型回圈中使用 var,可以從迭代器中推斷出型別,如清單 4 所示,
清單 4. 在回圈中使用 var
for(var book : books){}
for(var i = 0; i < 10; i++){}
使用這種型別的最明顯的原因是為了減少代碼中的冗長, 看看清單 5 中的示例,
清單 5. 很長的型別名稱使得代碼很長
String message = "Incy wincy spider...";
StringReader reader = new StringReader(message);
StreamTokenizer tokenizer = new StreamTokenizer(reader);
請注意,使用 var 保留型別名稱重寫清單5時發生了什么,
清單 6. var 型別減少了代碼的冗長性
var message = "Incy wincy spider...";
var reader = new StringReader(message);
var tokenizer = new StreamTokenizer(reader);
清單 6 中的型別宣告是垂直排列的,并且在建構式呼叫的右側每個申明中都會提到一次型別, 想象一下使用這種型別在一些 Java 框架中常見的長類名的好處,
區域變數型別的問題
1. var 掩蓋了型別
你已經看到了 var 如何提高代碼的可讀性,但是從另一方面來看,它也可以掩蓋它, 看看清單7中的示例,
清單 7. 回傳型別不清楚
var result = searchService.retrieveTopResult();
在清單 7 中,我們必須猜測回傳型別, 讓讀者猜測發生了什么的代碼是難以維護的,
2. var 不能與 lambda 一起使用
與 lambda 運算式一起使用時,型別推斷效果不佳,主要原因是編譯器缺少型別資訊, 清單8中的 lambda 運算式不會被編譯,
清單 8. 型別資訊不足
Function<String, String> quotify = m -> "'" + message + "'";
var quotify = m -> "'" + message + "'";
在清單 8 中,編譯器的右邊運算式中沒有足夠的型別資訊來推斷變數型別, Lambda 陳述句必須始終宣告一個顯式型別,
3. var 不會與菱形運算子混在一起
與菱形運算子一起使用時,型別推斷也不能很好地作業, 看看清單 9 中的例子,
清單 9. 使用帶有 var 的菱形運算子
var books = new ArrayList <>();
親自嘗試一下
想要親自嘗試本地變數型別推斷,您需要下載 JDK 10 和一個支持它的 IDE, IntelliJ 的 EAP(Early Access Program)版本具有此支持, 一旦你下載并安裝了它,你可以從本文附帶的 GitHub 存盤庫中檢出代碼開始, 你會在那里找到區域變數型別推斷的例子,
在代碼清單 9 中,books 的 ArrayList 的引數型別是什么呢?你可能明白你是希望 ArrayList 存盤一個書的串列,但是編譯器不能推斷出來,反之,編譯器會做的唯一它能做的事情,就是推斷出來這是一個引數是 Object型別ArrayList:ArrayList
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/176242.html
標籤:Java
