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