轉帖|行業資訊|編輯:龔雪|2023-03-07 10:20:22.903|閱讀 173 次
概述:IntelliJ IDEA在最新版本中發布支持Java 19,一起來看看有哪些新變化吧~
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
Java仍然是目前比較流行的編程語言,它更短的發布節奏讓開發者每六個月左右就可以試用新的語言或平臺功能,IntelliJ IDEA幫助我們更流暢地發現和使用這些新功能。
Jetbrains技術交流群(QQ):786598704 歡迎一起進群討論
在本文中,我們將只介紹Java 19的語言功能:記錄模式和switch模式匹配(第三版預覽),特意避開其他Java 19功能,例如預覽API虛擬線程。IntelliJ IDEA支持虛擬線程的基本語法高亮顯示,官方團隊正努力在調試器和分析器中添加對虛擬線程的支持。
記錄模式簡化了對記錄組件的訪問,比較記錄模式和記錄析構 – 當實例與記錄結構匹配時,將記錄組件的值提取到一組變量,它與 switch 和密封類的模式匹配等其他語言功能結合使用時,效果十分驚人。
switch 的模式匹配將模式添加到 switch 語句和 switch 表達式中的 case 標簽,可以與 switch 一起使用的選擇器表達式的類型擴展為任意引用值。 另外case 標簽不再限于常量值,它還有助于將 if-else 語句鏈替換為 switch,提高代碼可讀性。 在這篇博文中,我們將介紹 switch 模式匹配第三版預覽中引入的更改。
先從為使用 Java 19 功能對IntelliJ IDEA 進行配置開始。
IntelliJ IDEA 2022.3 中提供了對 Java 19 的支持,未來的 IntelliJ IDEA 版本將提供更多支持。 要通過 Java 19 使用 switch 的模式匹配,先轉到 Project Settings | Project(項目設置 | 項目),將 Project SDK(項目 SDK)設為 19,然后將項目語言級別設置為 19 (Preview) – Record patterns, pattern matching for switch (third preview):
開發者可以使用系統上已經下載的任意版本JDK,也可以點擊 Edit(編輯),然后選擇 Add SDK >(添加 SDK)、Download JDK…(下載 JDK…)來下載其他版本,可以從供應商列表中選擇要下載的 JDK 版本。
在 Modules(模塊)選項卡上,確保為模塊選擇相同的語言級別 – 19 (Preview) – Record patterns, pattern matching for switch (third preview):
選擇此選項后,可能會出現以下彈出窗口,通知您 IntelliJ IDEA 可能會在后續版本中停止對 Java 預覽語言功能的支持。 因為預覽功能(暫且)不是永久性的,并且它可能在未來的 Java 版本中發生變化(甚至被移除)。
數據是大多數應用程序的核心,通常開發者使用的應用程序可以查找數據,或者以幫助開發者做出決策的方式處理數據。當然如果應用程序無法存儲、檢索或處理其數據,這是不可行的。
在最近的一個 Java 版本(第 16 版)中,記錄被添加到 Java 語言中,讓開發者可以輕松處理數據。 記錄大幅簡化了對不可變數據建模的方式,它們充當數據的透明載體或包裝器,只需使用一行代碼,就可以定義一條記錄及其組件。
例如,以下單行代碼會創建一條新記錄 Person,后者可以存儲其組件 name 的字符串值和 age 的整數值:
record Person (String name, int age) { }
記錄讓開發者不必些示例代碼,記錄會隱式生成其構造函數的默認實現、其組件的訪問器方法,以及 toString、equals 和 hashCode 等效用函數方法。 使用記錄作為數據的包裝器時,您很可能需要將其展開來訪問其組件。 例如,對于記錄 Person 的實例,可能想要檢查其年齡組件以確定它所代表的人是否有資格投票,isEligibleToVote 這樣的方法可以完成這個操作:
boolean isEligibleToVote(Object obj) { if (obj instanceof Person person) { return person.age() >= 18; } return false; }
前面的示例使用了 instanceof 的模式匹配,它聲明了一個模式變量 person,因此您不需要創建局部變量來將 obj 轉換為 Person。
記錄模式更進一步。 它不僅將實例與記錄類型 Person 比較,還聲明了記錄組件的變量,因此無需定義局部變量或使用模式變量來訪問記錄的組件,這都要歸功于編譯器知道記錄組件的確切數量和類型。
使用記錄模式重寫前面的方法,將記錄類型與 instanceof 運算符配合使用或在 switch case 標簽中使用時,IntelliJ IDEA可以檢測到它并建議使用記錄模式:
這是修改后的代碼:
boolean isEligibleToVote(Object obj) { if (obj instanceof Person(String name, int age)) { return age >= 18; } return false; }
在前面的代碼中,記錄模式 Person(String name, int age) 似乎允許使用變量 age 代替 person.age()。 然而繼續閱讀,將了解記錄模式能夠簡化代碼的意圖,還有助于創建簡潔的數據處理代碼。
記錄模式后面可以跟隨一個記錄模式變量,這種情況下,記錄模式被稱為命名記錄模式(雖然沒有得到確認,但 Java 20 的記錄模式的第二版預覽可能會放棄對命名記錄模式的支持)。
記錄模式還可以為其組件定義模式變量,用命名記錄模式并嘗試使用記錄模式變量訪問其組件時,IntelliJ IDEA 會提示您為其組件使用模式變量,將看到此類代碼以黃色背景高亮顯示,可以使用 Alt+Enter 查看建議,并接受修改代碼的建議:
我們回顧一下上一部分中的 isEligibleToVote 方法示例,如果將 null 值傳遞給以下方法會發生什么:
boolean isEligibleToVote(Object obj) { if (obj instanceof Person(String name, int age)) { return age >= 18; } return false; }
由于 null 不是記錄模式 Person(String name, int age) 的實例,instanceof 運算符返回 false,并且模式變量 name 和 age 未初始化。這很方便,因為記錄模式會處理null,開發者不需要定義非 null 檢查。
但是如果組件 name 的值為 null,則模式將被匹配。
將另一條記錄定義為其組件的記錄相當常見,例如:
record Name (String fName, String lName) { } record PhoneNumber(String areaCode, String number) { } record Country (String countryCode, String countryName) { } record Passenger (Name name, PhoneNumber phoneNumber, Country from, Country destination) { }
如果沒有可以檢查 null 組件值的記錄模式,您將需要幾個 null 檢查運算來處理記錄 Passenger 的 fName 和 countryCode 的組件值,如下所示:
boolean checkFirstNameAndCountryCode (Object obj) { if (obj != null) { if (obj instanceof Passenger passenger) { Name name = null; Country destination = null; if (passenger.name() != null) { name = passenger.name(); if (passenger.destination() != null) { destination = passenger.destination(); String fName = name.fName(); String countryCode = destination.countryCode(); if (fName != null && countryCode != null) { return fName.startsWith("Simo") && countryCode.equals("PRG"); } } } } } return false; }
同樣的行為可以通過嵌套記錄模式實現,這也將使代碼的意圖更加清晰。 如果記錄組件 name 和 destination 為 null,instanceof 檢查將失敗:
boolean checkFirstNameAndCountryCodeAgain (Object obj) { if (obj instanceof Passenger(Name (String fName, String lName), PhoneNumber phoneNumber, Country from, Country (String countryCode, String countryName) )) { if (fName != null && countryCode != null) { return fName.startsWith("Simo") && countryCode.equals("PRG"); } } return false; }
如前面的示例代碼所示,開發者可以有選擇地添加主記錄組件的記錄模式。 例如前面的示例沒有為組件 from 使用記錄模式,但它為主記錄 Passenger 的記錄組件目標使用記錄模式。 簡而言之,定義記錄模式時,開發者可以控制要提取到模式變量的詳細信息,這一功能非常適合數據處理密集型應用程序。
來回顧一下前面示例中的方法 checkFirstNameAndCountryCodeAgain,并將一些模式變量的類型定義為 var:
boolean checkFirstNameAndCountryCodeAgain (Object obj) { if (obj instanceof Passenger(Name (String fName, var lName), var phoneNumber, Country from, Country (var countryCode, String countryName) )) { if (fName != null && countryCode != null) { return fName.startsWith("Simo") && countryCode.equals("PRG"); } } return false; }
開發者可以將部分或全部模式變量的類型定義為var,如果您好奇它們的類型,IntelliJ IDEA 可以顯示:
如果記錄是泛型,則其記錄模式必須使用泛型類型。 例如假設類 WristWatch 和泛型記錄 Gift 的定義如下:
class WristWatch {} record Gift<T>(T t) {}
開發者可以使用以下方法解開記錄 Gift 的實例,可以使用 var 或 WristWatch 作為模式變量 watch 的類型:
void unwrap(Gift<WristWatch> obj) { if (obj instanceof Gift<WristWatch> (var watch)) { System.out.println(watch); } }
但是,以下代碼將不起作用:
static void cannotUnwap(Gift<object> obj) { if (obj instanceof Gift(var s)) { // won’t compile //.. } }
下一部分使用記錄模式和 switch 表達式創建強大的遞歸方法。
結合記錄模式、switch 表達式和密封類,開發者可以創建功能強大、簡潔且富有表現力的代碼來處理數據。 這是密封接口 TwoDimensional 的示例,它由記錄 Point、Line、Triangle 和 Square 實現:
sealed interface TwoDimensional {} record Point (int x, int y) implements TwoDimensional { } record Line ( Point start, Point end) implements TwoDimensional { } record Triangle( Point pointA, Point pointB, Point PointC) implements TwoDimensional { } record Square ( Point pointA, Point pointB, Point PointC, Point pointD) implements TwoDimensional { }
下面的方法定義了一個遞歸方法進程,它使用 switch 構造返回二維圖形(如 Line、Triangle 或 Square)中所有點的 x 和 y 坐標之和:
static int process(TwoDimensional twoDim) { return switch (twoDim) { case Point(int x, int y) -> x + y; case Line(Point a, Point b) -> process(a) + process(b); case Triangle(Point a, Point b, Point c) -> process(a) + process(b) + process(c); case Square(Point a, Point b, Point c, Point d) -> process(a) + process(b) + process(c) + process(d); }; }
IntelliJ IDEA 還會在此方法的間距中顯示遞歸調用圖標:
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:慧都網