Java 15 正式發(fā)布, 好多新特性,刷新你的認(rèn)知?。?/h1>
簡(jiǎn)介
一年兩次的JDK最新版本JDK15在2020年9月15日正式發(fā)布了,這次的JDK15給我們帶了隱藏類,EdDSA,模式匹配,Records,封閉類和Text Block等諸多新特性。
一起來看看吧。
JDK15的新特性
01
JEP 385 Deprecate RMI Activation for Removal
RMI Activation被標(biāo)記為Deprecate,將會(huì)在未來的版本中刪除。
RMI大家應(yīng)該都清楚,RMI就是Remote Method Invocation,翻譯成中文就是遠(yuǎn)程方法調(diào)用,是在JDK1.2中引入的。
RMI為java提供了開發(fā)分布式系統(tǒng)的強(qiáng)大能力。而J2EE的規(guī)范EJB就是使用RMI來實(shí)現(xiàn)的bean的遠(yuǎn)程調(diào)用的。
在RMI系統(tǒng)中,遠(yuǎn)程系統(tǒng)中存在很多分布式對(duì)象,如果這些分布式對(duì)象一直處于活動(dòng)狀態(tài)的話,將會(huì)占用很多寶貴的系統(tǒng)資源。
于是RMI引入了一種lazy Activation的方式,這種方式就叫做延遲激活。
這里有兩個(gè)概念,活動(dòng)對(duì)象和被動(dòng)對(duì)象。
活動(dòng)對(duì)象是在某些系統(tǒng)上的JVM中實(shí)例化并對(duì)外暴露的遠(yuǎn)程對(duì)象。被動(dòng)對(duì)象是尚未在JVM中實(shí)例化(或暴露)但可以進(jìn)入主動(dòng)狀態(tài)的對(duì)象。
將被動(dòng)對(duì)象轉(zhuǎn)換為主動(dòng)對(duì)象的過程稱為激活。激活要求對(duì)象與JVM關(guān)聯(lián),這可能會(huì)將該對(duì)象的類加載到JVM中,并且將該對(duì)象恢復(fù)為之前的狀態(tài)。
在RMI系統(tǒng)中,我們使用延遲激活。延遲激活將激活對(duì)象推遲到客戶第一次使用(即第一次方法調(diào)用)之前。
既然RMI Activation這么好用,為什么要廢棄呢?
因?yàn)閷?duì)于現(xiàn)代應(yīng)用程序來說,分布式系統(tǒng)大部分都是基于Web的,web服務(wù)器已經(jīng)解決了穿越防火墻,過濾請(qǐng)求,身份驗(yàn)證和安全性的問題,并且也提供了很多延遲加載的技術(shù)。
所以在現(xiàn)代應(yīng)用程序中,RMI Activation已經(jīng)很少被使用到了。并且在各種開源的代碼庫(kù)中,也基本上找不到RMI Activation的使用代碼了。
為了減少RMI Activation的維護(hù)成本,在JDK8中,RMI Activation被置為可選的。現(xiàn)在在JDK15中,終于可以廢棄了。
02
JEP 371 Hidden Classes
Hidden Classes是什么呢?
Hidden Classes就是不能直接被其他class的二凈值代碼使用的class。Hidden Classes主要被一些框架用來生成運(yùn)行時(shí)類,但是這些類不是被用來直接使用的,而是通過反射機(jī)制來調(diào)用。
通常來說基于JVM的很多語言都有動(dòng)態(tài)生成類的機(jī)制,這樣可以提高語言的靈活性和效率。
比如在JDK8中引入的lambda表達(dá)式,JVM并不會(huì)在編譯的時(shí)候?qū)ambda表達(dá)式轉(zhuǎn)換成為專門的類,而是在運(yùn)行時(shí)將相應(yīng)的字節(jié)碼動(dòng)態(tài)生成相應(yīng)的類對(duì)象。
另外使用動(dòng)態(tài)代理也可以為某些類生成新的動(dòng)態(tài)類。
那么我們希望這些動(dòng)態(tài)生成的類需要具有什么特性呢?
不可發(fā)現(xiàn)性。因?yàn)槲覀兪菫槟承╈o態(tài)的類動(dòng)態(tài)生成的動(dòng)態(tài)類,所以我們希望把這個(gè)動(dòng)態(tài)生成的類看做是靜態(tài)類的一部分。所以我們不希望除了該靜態(tài)類之外的其他機(jī)制發(fā)現(xiàn)。
訪問控制。我們希望在訪問控制靜態(tài)類的同時(shí),也能控制到動(dòng)態(tài)生成的類。
生命周期。動(dòng)態(tài)生成類的生命周期一般都比較短,我們并不需要將其保存和靜態(tài)類的生命周期一致。
但是現(xiàn)有的類的定義API ClassLoader::defineClass和Lookup::defineClass是不管類的字節(jié)碼是如何生成的,他們都是平等對(duì)待。
所以我們需要一些API來定義無法發(fā)現(xiàn)的且具有有限生命周期的隱藏類。這將提高所有基于JVM的語言實(shí)現(xiàn)的效率。
比如:
java.lang.reflect.Proxy可以定義隱藏類作為實(shí)現(xiàn)代理接口的代理類。
java.lang.invoke.StringConcatFactory可以生成隱藏類來保存常量連接方法;
java.lang.invoke.LambdaMetaFactory可以生成隱藏的nestmate類,以容納訪問封閉變量的lambda主體;
JavaScript引擎可以為從JavaScript程序轉(zhuǎn)換的字節(jié)碼生成隱藏的類,因?yàn)楫?dāng)引擎不再使用它們時(shí),這些類將被卸載。
普通類是通過調(diào)用ClassLoader::defineClass創(chuàng)建的,而隱藏類是通過調(diào)用Lookup::defineHiddenClass創(chuàng)建的。
這使JVM從提供的字節(jié)中派生一個(gè)隱藏類,鏈接該隱藏類,并返回提供對(duì)隱藏類的反射訪問的查找對(duì)象。
調(diào)用程序可以通過返回的查找對(duì)象來獲取隱藏類的Class對(duì)象。
03
JEP 339 Edwards-Curve Digital Signature Algorithm (EdDSA)
實(shí)現(xiàn)了EdDSA橢圓曲線簽名算法。
這里就不多講橢圓曲線簽名算法了,如果又想了解的朋友可以給我留言。
04
JEP 375 Pattern Matching for instanceof (Second Preview)
Pattern Matching 就是說可以在做pattern mathching的時(shí)候,直接對(duì)該對(duì)象進(jìn)行類型的轉(zhuǎn)換。
現(xiàn)在這個(gè)特性還是預(yù)覽版本的。
我們看一下具體的例子:
if (obj instanceof String) { String s = (String) obj; // use s}
在Pattern Matching之前,我們使用instanceof之后,還需要對(duì)該對(duì)象進(jìn)行強(qiáng)制類型轉(zhuǎn)換才能使用。
但是在Pattern Matching之后,我們可以這樣用:
if (obj instanceof String s) { // can use s here} else { // can't use s here}
是不是很方便。
05
JEP 384 Records (Second Preview)
Record是一種輕量級(jí)的class,可以看做是數(shù)據(jù)結(jié)構(gòu)體。和scala中的case有點(diǎn)相似。
舉個(gè)自定義User的例子看一下Record是怎么用的:
public record Address( String addressName, String city) {}
public record CustUser( String firstName, String lastName, Address address, int age) {}
上面我們定義了兩個(gè)類,CustUser和Address。CustUser中引用了Address。
Record和普通的類的區(qū)別就在于Record多了一個(gè)括號(hào)括起來的定義的字段。
Record類默認(rèn)是final的,里面的字段默認(rèn)是private final的。
要想知道Record到底是怎么工作的,我們可以使用javap來對(duì)編譯好的class文件反編譯,運(yùn)行javap CustUser,可以得到下面的結(jié)果:
警告: 二進(jìn)制文件CustUser包含com.flydean.records.CustUserCompiled from "CustUser.java"public final class com.flydean.records.CustUser extends java.lang.Record { public com.flydean.records.CustUser(java.lang.String, java.lang.String, com.flydean.records.Address, int); public java.lang.String toString(); public final int hashCode(); public final boolean equals(java.lang.Object); public java.lang.String firstName(); public java.lang.String lastName(); public com.flydean.records.Address address(); public int age();}
上面可以看到final class CustUser繼承自java.lang.Record。
并且自動(dòng)添加了默認(rèn)帶有所有字段的構(gòu)造函數(shù)。
各個(gè)自動(dòng)的獲取方法,并實(shí)現(xiàn)了toString,hashCode和equals方法。
天啦,太完美了,我們想要的它居然都有。
如果上面的javap還不是很清楚的話,大家可以借助IDE的反編譯功能,打開CustUser.class文件看一看:
public final class CustUser extends java.lang.Record { private final java.lang.String firstName; private final java.lang.String lastName; private final com.flydean.records.Address address; private final int age;
public CustUser(java.lang.String firstName, java.lang.String lastName, com.flydean.records.Address address, int age) { /* compiled code */ }
public java.lang.String toString() { /* compiled code */ }
public final int hashCode() { /* compiled code */ }
public final boolean equals(java.lang.Object o) { /* compiled code */ }
public java.lang.String firstName() { /* compiled code */ }
public java.lang.String lastName() { /* compiled code */ }
public com.flydean.records.Address address() { /* compiled code */ }
public int age() { /* compiled code */ }}
注意,上面的反編譯我們可以看到,record中的所有字段都是final的,只能在初始化的時(shí)候設(shè)置。并且方法里面也沒有提供其他可以改變字段內(nèi)容的方法。
所以我們得出了一個(gè)震世驚俗的結(jié)論:record是immutable的。
上面的例子中我們只使用了小括號(hào)里面的內(nèi)容,大括號(hào)還是空的呀??刹豢梢韵衿渌5念愐粯樱砑狱c(diǎn)方法或者構(gòu)造函數(shù)進(jìn)去呢?
答案是肯定的。
先看一個(gè)整體的方案:
public record CustUserWithBody( String firstName, String lastName, Address address, int age) { public String fullName(){ return firstName+ lastName; }
public CustUserWithBody{ if (age < 18) { throw new IllegalArgumentException( "男大當(dāng)婚,女大當(dāng)嫁,18歲未到,不許出嫁!"); } }}
我們?cè)趓ecord的主題中,定義了一個(gè)方法和一個(gè)構(gòu)造函數(shù)。
先看這個(gè)方法,在方法中我們可以訪問到record中定義的變量,但是千萬不要嘗試去修改他們,因?yàn)樗麄兪莊inal的,你會(huì)得到一個(gè)變異錯(cuò)誤。
再看這個(gè)構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)沒有小括號(hào),只有大括號(hào),這種構(gòu)造函數(shù)叫做Compact constructor。你無法在record中定義正常的構(gòu)造函數(shù),因?yàn)闀?huì)得到一個(gè)編譯錯(cuò)誤。
在這個(gè)Compact constructor中,我們可以對(duì)定義的字段進(jìn)行數(shù)據(jù)校驗(yàn)。如上所述。
06
JEP 360 Sealed Classes (Preview)
在Java中,類層次結(jié)構(gòu)通過繼承實(shí)現(xiàn)代碼的重用,父類的方法可以被許多子類繼承。
但是,類層次結(jié)構(gòu)的目的并不總是重用代碼。有時(shí),其目的是對(duì)域中存在的各種可能性進(jìn)行建模,例如圖形庫(kù)支持的形狀類型或金融應(yīng)用程序支持的貸款類型。
當(dāng)以這種方式使用類層次結(jié)構(gòu)時(shí),我們可能需要限制子類集從而來簡(jiǎn)化建模。
因?yàn)槲覀円肓藄ealed class或interfaces,這些class或者interfaces只允許被指定的類或者interface進(jìn)行擴(kuò)展和實(shí)現(xiàn)。
舉個(gè)例子:
package com.example.geometry;public abstract sealed class Shape permits Circle, Rectangle, Square {...}
上面的例子中,我們指定了Shape只允許被Circle, Rectangle, Square來繼承。
上面的例子中并沒有指定類的包名,我們可以這樣寫:
package com.example.geometry;public abstract sealed class Shape permits com.example.polar.Circle, com.example.quad.Rectangle, com.example.quad.simple.Square {...}
07
JEP 378 Text Blocks
Text Blocks是為了解決在java中輸入多行數(shù)據(jù)的問題。
比如:
String html = "\n" + " \n" + " Hello, world
\n" + " \n" + "\n";
可以寫成:
String html = """ Hello, world
""";
String query = "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n" + "WHERE \"CITY\" = 'INDIANAPOLIS'\n" + "ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";
可以寫成:
String query = """ SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB" WHERE "CITY" = 'INDIANAPOLIS' ORDER BY "EMP_ID", "LAST_NAME";
非常的方便。
---END---
長(zhǎng)按進(jìn)入小程序,進(jìn)行30天打卡
(更多精彩值得期待……)

最近熱文: 史上首例!程序員寫的代碼,被國(guó)家博物館收藏了!
機(jī)房布線的最高境界 | 最后的暗黑系,真是亮瞎眼
阿里發(fā)布第一臺(tái)云電腦 “無影”,傳統(tǒng) PC 電腦會(huì)被淘汰嗎?
Windows給力!可以扔掉Linux虛擬機(jī)了!
華為鴻蒙OS上嘗鮮跑了個(gè)“hello world”!
程序員常用工具和網(wǎng)站集合(建議收藏) LeetCode1-40題匯總,速度收藏!
2T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,人工智能,考研,軟考,英語,等等。在公眾號(hào)內(nèi)回復(fù)「資源」,即可免費(fèi)獲??!回復(fù)「社群」,可以邀請(qǐng)你加入讀者群!
點(diǎn)個(gè)在看少個(gè) bug??
瀏覽
53
簡(jiǎn)介
一年兩次的JDK最新版本JDK15在2020年9月15日正式發(fā)布了,這次的JDK15給我們帶了隱藏類,EdDSA,模式匹配,Records,封閉類和Text Block等諸多新特性。
一起來看看吧。
JDK15的新特性
01
JEP 385 Deprecate RMI Activation for Removal
RMI Activation被標(biāo)記為Deprecate,將會(huì)在未來的版本中刪除。
RMI大家應(yīng)該都清楚,RMI就是Remote Method Invocation,翻譯成中文就是遠(yuǎn)程方法調(diào)用,是在JDK1.2中引入的。
RMI為java提供了開發(fā)分布式系統(tǒng)的強(qiáng)大能力。而J2EE的規(guī)范EJB就是使用RMI來實(shí)現(xiàn)的bean的遠(yuǎn)程調(diào)用的。
在RMI系統(tǒng)中,遠(yuǎn)程系統(tǒng)中存在很多分布式對(duì)象,如果這些分布式對(duì)象一直處于活動(dòng)狀態(tài)的話,將會(huì)占用很多寶貴的系統(tǒng)資源。
于是RMI引入了一種lazy Activation的方式,這種方式就叫做延遲激活。
這里有兩個(gè)概念,活動(dòng)對(duì)象和被動(dòng)對(duì)象。
活動(dòng)對(duì)象是在某些系統(tǒng)上的JVM中實(shí)例化并對(duì)外暴露的遠(yuǎn)程對(duì)象。被動(dòng)對(duì)象是尚未在JVM中實(shí)例化(或暴露)但可以進(jìn)入主動(dòng)狀態(tài)的對(duì)象。
將被動(dòng)對(duì)象轉(zhuǎn)換為主動(dòng)對(duì)象的過程稱為激活。激活要求對(duì)象與JVM關(guān)聯(lián),這可能會(huì)將該對(duì)象的類加載到JVM中,并且將該對(duì)象恢復(fù)為之前的狀態(tài)。
在RMI系統(tǒng)中,我們使用延遲激活。延遲激活將激活對(duì)象推遲到客戶第一次使用(即第一次方法調(diào)用)之前。
既然RMI Activation這么好用,為什么要廢棄呢?
因?yàn)閷?duì)于現(xiàn)代應(yīng)用程序來說,分布式系統(tǒng)大部分都是基于Web的,web服務(wù)器已經(jīng)解決了穿越防火墻,過濾請(qǐng)求,身份驗(yàn)證和安全性的問題,并且也提供了很多延遲加載的技術(shù)。
所以在現(xiàn)代應(yīng)用程序中,RMI Activation已經(jīng)很少被使用到了。并且在各種開源的代碼庫(kù)中,也基本上找不到RMI Activation的使用代碼了。
為了減少RMI Activation的維護(hù)成本,在JDK8中,RMI Activation被置為可選的。現(xiàn)在在JDK15中,終于可以廢棄了。
02
JEP 371 Hidden Classes
Hidden Classes是什么呢?
Hidden Classes就是不能直接被其他class的二凈值代碼使用的class。Hidden Classes主要被一些框架用來生成運(yùn)行時(shí)類,但是這些類不是被用來直接使用的,而是通過反射機(jī)制來調(diào)用。
通常來說基于JVM的很多語言都有動(dòng)態(tài)生成類的機(jī)制,這樣可以提高語言的靈活性和效率。
比如在JDK8中引入的lambda表達(dá)式,JVM并不會(huì)在編譯的時(shí)候?qū)ambda表達(dá)式轉(zhuǎn)換成為專門的類,而是在運(yùn)行時(shí)將相應(yīng)的字節(jié)碼動(dòng)態(tài)生成相應(yīng)的類對(duì)象。
另外使用動(dòng)態(tài)代理也可以為某些類生成新的動(dòng)態(tài)類。
那么我們希望這些動(dòng)態(tài)生成的類需要具有什么特性呢?
不可發(fā)現(xiàn)性。因?yàn)槲覀兪菫槟承╈o態(tài)的類動(dòng)態(tài)生成的動(dòng)態(tài)類,所以我們希望把這個(gè)動(dòng)態(tài)生成的類看做是靜態(tài)類的一部分。所以我們不希望除了該靜態(tài)類之外的其他機(jī)制發(fā)現(xiàn)。
訪問控制。我們希望在訪問控制靜態(tài)類的同時(shí),也能控制到動(dòng)態(tài)生成的類。
生命周期。動(dòng)態(tài)生成類的生命周期一般都比較短,我們并不需要將其保存和靜態(tài)類的生命周期一致。
但是現(xiàn)有的類的定義API ClassLoader::defineClass和Lookup::defineClass是不管類的字節(jié)碼是如何生成的,他們都是平等對(duì)待。
所以我們需要一些API來定義無法發(fā)現(xiàn)的且具有有限生命周期的隱藏類。這將提高所有基于JVM的語言實(shí)現(xiàn)的效率。
比如:
java.lang.reflect.Proxy可以定義隱藏類作為實(shí)現(xiàn)代理接口的代理類。
java.lang.invoke.StringConcatFactory可以生成隱藏類來保存常量連接方法;
java.lang.invoke.LambdaMetaFactory可以生成隱藏的nestmate類,以容納訪問封閉變量的lambda主體;
JavaScript引擎可以為從JavaScript程序轉(zhuǎn)換的字節(jié)碼生成隱藏的類,因?yàn)楫?dāng)引擎不再使用它們時(shí),這些類將被卸載。
普通類是通過調(diào)用ClassLoader::defineClass創(chuàng)建的,而隱藏類是通過調(diào)用Lookup::defineHiddenClass創(chuàng)建的。
這使JVM從提供的字節(jié)中派生一個(gè)隱藏類,鏈接該隱藏類,并返回提供對(duì)隱藏類的反射訪問的查找對(duì)象。
調(diào)用程序可以通過返回的查找對(duì)象來獲取隱藏類的Class對(duì)象。
03
JEP 339 Edwards-Curve Digital Signature Algorithm (EdDSA)
實(shí)現(xiàn)了EdDSA橢圓曲線簽名算法。
這里就不多講橢圓曲線簽名算法了,如果又想了解的朋友可以給我留言。
04
JEP 375 Pattern Matching for instanceof (Second Preview)
Pattern Matching 就是說可以在做pattern mathching的時(shí)候,直接對(duì)該對(duì)象進(jìn)行類型的轉(zhuǎn)換。
現(xiàn)在這個(gè)特性還是預(yù)覽版本的。
我們看一下具體的例子:
if (obj instanceof String) {String s = (String) obj;// use s}
在Pattern Matching之前,我們使用instanceof之后,還需要對(duì)該對(duì)象進(jìn)行強(qiáng)制類型轉(zhuǎn)換才能使用。
但是在Pattern Matching之后,我們可以這樣用:
if (obj instanceof String s) {// can use s here} else {// can't use s here}
是不是很方便。
05
JEP 384 Records (Second Preview)
Record是一種輕量級(jí)的class,可以看做是數(shù)據(jù)結(jié)構(gòu)體。和scala中的case有點(diǎn)相似。
舉個(gè)自定義User的例子看一下Record是怎么用的:
public record Address(String addressName,String city) {}
public record CustUser(String firstName,String lastName,Address address,int age) {}
上面我們定義了兩個(gè)類,CustUser和Address。CustUser中引用了Address。
Record和普通的類的區(qū)別就在于Record多了一個(gè)括號(hào)括起來的定義的字段。
Record類默認(rèn)是final的,里面的字段默認(rèn)是private final的。
要想知道Record到底是怎么工作的,我們可以使用javap來對(duì)編譯好的class文件反編譯,運(yùn)行javap CustUser,可以得到下面的結(jié)果:
警告: 二進(jìn)制文件CustUser包含com.flydean.records.CustUserCompiled from "CustUser.java"public final class com.flydean.records.CustUser extends java.lang.Record {public com.flydean.records.CustUser(java.lang.String, java.lang.String, com.flydean.records.Address, int);public java.lang.String toString();public final int hashCode();public final boolean equals(java.lang.Object);public java.lang.String firstName();public java.lang.String lastName();public com.flydean.records.Address address();public int age();}
上面可以看到final class CustUser繼承自java.lang.Record。
并且自動(dòng)添加了默認(rèn)帶有所有字段的構(gòu)造函數(shù)。
各個(gè)自動(dòng)的獲取方法,并實(shí)現(xiàn)了toString,hashCode和equals方法。
天啦,太完美了,我們想要的它居然都有。
如果上面的javap還不是很清楚的話,大家可以借助IDE的反編譯功能,打開CustUser.class文件看一看:
public final class CustUser extends java.lang.Record {private final java.lang.String firstName;private final java.lang.String lastName;private final com.flydean.records.Address address;private final int age;public CustUser(java.lang.String firstName, java.lang.String lastName, com.flydean.records.Address address, int age) { /* compiled code */ }public java.lang.String toString() { /* compiled code */ }public final int hashCode() { /* compiled code */ }public final boolean equals(java.lang.Object o) { /* compiled code */ }public java.lang.String firstName() { /* compiled code */ }public java.lang.String lastName() { /* compiled code */ }public com.flydean.records.Address address() { /* compiled code */ }public int age() { /* compiled code */ }}
注意,上面的反編譯我們可以看到,record中的所有字段都是final的,只能在初始化的時(shí)候設(shè)置。并且方法里面也沒有提供其他可以改變字段內(nèi)容的方法。
所以我們得出了一個(gè)震世驚俗的結(jié)論:record是immutable的。
上面的例子中我們只使用了小括號(hào)里面的內(nèi)容,大括號(hào)還是空的呀??刹豢梢韵衿渌5念愐粯樱砑狱c(diǎn)方法或者構(gòu)造函數(shù)進(jìn)去呢?
答案是肯定的。
先看一個(gè)整體的方案:
public record CustUserWithBody(String firstName,String lastName,Address address,int age) {public String fullName(){return firstName+ lastName;}public CustUserWithBody{if (age < 18) {throw new IllegalArgumentException( "男大當(dāng)婚,女大當(dāng)嫁,18歲未到,不許出嫁!");}}}
我們?cè)趓ecord的主題中,定義了一個(gè)方法和一個(gè)構(gòu)造函數(shù)。
先看這個(gè)方法,在方法中我們可以訪問到record中定義的變量,但是千萬不要嘗試去修改他們,因?yàn)樗麄兪莊inal的,你會(huì)得到一個(gè)變異錯(cuò)誤。
再看這個(gè)構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)沒有小括號(hào),只有大括號(hào),這種構(gòu)造函數(shù)叫做Compact constructor。你無法在record中定義正常的構(gòu)造函數(shù),因?yàn)闀?huì)得到一個(gè)編譯錯(cuò)誤。
在這個(gè)Compact constructor中,我們可以對(duì)定義的字段進(jìn)行數(shù)據(jù)校驗(yàn)。如上所述。
06
JEP 360 Sealed Classes (Preview)
在Java中,類層次結(jié)構(gòu)通過繼承實(shí)現(xiàn)代碼的重用,父類的方法可以被許多子類繼承。
但是,類層次結(jié)構(gòu)的目的并不總是重用代碼。有時(shí),其目的是對(duì)域中存在的各種可能性進(jìn)行建模,例如圖形庫(kù)支持的形狀類型或金融應(yīng)用程序支持的貸款類型。
當(dāng)以這種方式使用類層次結(jié)構(gòu)時(shí),我們可能需要限制子類集從而來簡(jiǎn)化建模。
因?yàn)槲覀円肓藄ealed class或interfaces,這些class或者interfaces只允許被指定的類或者interface進(jìn)行擴(kuò)展和實(shí)現(xiàn)。
舉個(gè)例子:
package com.example.geometry;public abstract sealed class Shapepermits Circle, Rectangle, Square {...}
上面的例子中,我們指定了Shape只允許被Circle, Rectangle, Square來繼承。
上面的例子中并沒有指定類的包名,我們可以這樣寫:
package com.example.geometry;public abstract sealed class Shapepermits com.example.polar.Circle,com.example.quad.Rectangle,com.example.quad.simple.Square {...}
07
JEP 378 Text Blocks
Text Blocks是為了解決在java中輸入多行數(shù)據(jù)的問題。
比如:
String html = "\n" +" \n" +"Hello, world
\n" +" \n" +"\n";
可以寫成:
String html = """Hello, world
""";
String query = "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n" +"WHERE \"CITY\" = 'INDIANAPOLIS'\n" +"ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";
可以寫成:
String query = """SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB"WHERE "CITY" = 'INDIANAPOLIS'ORDER BY "EMP_ID", "LAST_NAME";
非常的方便。
長(zhǎng)按進(jìn)入小程序,進(jìn)行30天打卡
(更多精彩值得期待……)
(更多精彩值得期待……)
最近熱文: 史上首例!程序員寫的代碼,被國(guó)家博物館收藏了!
機(jī)房布線的最高境界 | 最后的暗黑系,真是亮瞎眼
阿里發(fā)布第一臺(tái)云電腦 “無影”,傳統(tǒng) PC 電腦會(huì)被淘汰嗎?
Windows給力!可以扔掉Linux虛擬機(jī)了!
華為鴻蒙OS上嘗鮮跑了個(gè)“hello world”!
程序員常用工具和網(wǎng)站集合(建議收藏) LeetCode1-40題匯總,速度收藏!
2T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,人工智能,考研,軟考,英語,等等。在公眾號(hào)內(nèi)回復(fù)「資源」,即可免費(fèi)獲??!回復(fù)「社群」,可以邀請(qǐng)你加入讀者群!
最近熱文: 史上首例!程序員寫的代碼,被國(guó)家博物館收藏了! 機(jī)房布線的最高境界 | 最后的暗黑系,真是亮瞎眼 阿里發(fā)布第一臺(tái)云電腦 “無影”,傳統(tǒng) PC 電腦會(huì)被淘汰嗎? Windows給力!可以扔掉Linux虛擬機(jī)了! 華為鴻蒙OS上嘗鮮跑了個(gè)“hello world”! 程序員常用工具和網(wǎng)站集合(建議收藏) LeetCode1-40題匯總,速度收藏!
2T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,人工智能,考研,軟考,英語,等等。在公眾號(hào)內(nèi)回復(fù)「資源」,即可免費(fèi)獲??!回復(fù)「社群」,可以邀請(qǐng)你加入讀者群!
點(diǎn)個(gè)在看少個(gè) bug??

