本篇內(nèi)容介紹了“JDK16有哪些新特性”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
創(chuàng)新互聯(lián)建站10多年企業(yè)網(wǎng)站制作服務(wù);為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁(yè)設(shè)計(jì)及高端網(wǎng)站定制服務(wù),企業(yè)網(wǎng)站制作及推廣,對(duì)自拌料攪拌車(chē)等多個(gè)方面擁有豐富的網(wǎng)站維護(hù)經(jīng)驗(yàn)的網(wǎng)站建設(shè)公司。
新特性一覽
在開(kāi)始之前,先讓我們來(lái)一起瀏覽一下JDK 16版本所帶來(lái)的17個(gè)新特性吧。? 本文將解讀的新特性
357: OpenJDK源代碼倉(cāng)庫(kù)從Mercurial遷移至Git。努力推動(dòng)這一改變,將會(huì)在版本控制系統(tǒng)元數(shù)據(jù)大小、可用工具以及托管等方面體現(xiàn)優(yōu)勢(shì)。369: 遷移到GitHub,這個(gè)變化是基于OpenJDK源碼庫(kù)遷移至Git的,JDK 16源代碼倉(cāng)庫(kù)將出現(xiàn)在最流行的程序員社交網(wǎng)站上。386: 在x64和AArch74架構(gòu)上,將JDK移植到Alpine Linux和其他使用musl作為其主要C庫(kù)的Linux發(fā)行版。Musl是 ISO C和Posix標(biāo)準(zhǔn)中描述的標(biāo)準(zhǔn)庫(kù)功能的Linux實(shí)現(xiàn)。Alpine Linux由于其鏡像小而被廣泛應(yīng)用于云部署、微服務(wù)以及容器環(huán)境中。Linux版本的Docker容器鏡像小于6MB。讓Java在此類(lèi)設(shè)置中開(kāi)箱即用地運(yùn)行,并允許Tomcat、Jetty、Spring和其它流行的框架在這些環(huán)境中工作。通過(guò)使用jlink來(lái)減少Java運(yùn)行時(shí)的大小,用戶(hù)可以創(chuàng)建一個(gè)更小的鏡像,以運(yùn)行特定的應(yīng)用程序。394: instanceof操作符的模式匹配,在JDK 14和JDK 15中都已預(yù)覽過(guò),將于JDK 16最終確定。模式匹配使程序中的通用邏輯(即從對(duì)象中有條件的提取組件)可以更簡(jiǎn)潔、更安全的表達(dá)。395: 提供Record記錄類(lèi),作為不可變數(shù)據(jù)的透明載體。? 其他的新特性
347: 啟用C++ 14語(yǔ)言功能,允許在JDK C++源代碼中使用C++ 14功能,并提供有關(guān)在HotSpot代碼中可以使用哪些功能的具體指導(dǎo)。376: 將ZGC(可擴(kuò)展低延遲垃圾收集器)線(xiàn)程堆棧處理從安全點(diǎn)移至并發(fā)階段。ZGC垃圾收集器旨在使HotSpot中的GC暫停和可伸縮性問(wèn)題成為過(guò)去。380: 添加Unix-Domain Socket Channels,其中Unix-Domain(AF_UNIX)套接字的支持被添加到nio.channels包中的Socket Channel和Server Socket Channel API中。387: 彈性Metaspace功能可將未使用的HotSpot虛擬機(jī)的Class Metadata(Metaspace)占用的內(nèi)存更迅速的返回給操作系統(tǒng),從而減少M(fèi)etaspace的占用并簡(jiǎn)化Metaspace的代碼以降低維護(hù)成本。388: 將JDK移植到Windows/AArch74平臺(tái)。389: 孵化階段的外部鏈接程序API,支持靜態(tài)類(lèi)型的純Java方式訪(fǎng)問(wèn)本地代碼。此計(jì)劃的目的在于通過(guò)用更高級(jí)的純Java開(kāi)發(fā)模式來(lái)替換JNI(Java本機(jī)接口),以提供與C語(yǔ)言的交互。它的性能將會(huì)比JNI更加優(yōu)越。390: 基于值的類(lèi)的警告建議:將原始包裝類(lèi)指定為基于值的類(lèi),棄用其構(gòu)造函數(shù)以進(jìn)行移除,并提示新的棄用警告。在Java平臺(tái)中對(duì)于任何基于值的類(lèi)的實(shí)例進(jìn)行同步的錯(cuò)誤嘗試會(huì)予以警告。392: 提供用于打包獨(dú)立的Java應(yīng)用程序的jpackage工具。396: 默認(rèn)情況下,JDK內(nèi)部結(jié)構(gòu)是強(qiáng)封裝的,而關(guān)鍵內(nèi)部API(例如misc.Unsafe)除外。此計(jì)劃的目標(biāo)包括提高JDK的安全性和可維護(hù)性,并鼓勵(lì)開(kāi)發(fā)人員從直接使用內(nèi)部元素逐漸遷移為使用標(biāo)準(zhǔn)API,這樣開(kāi)發(fā)人員和最終用戶(hù)都可以輕松地升級(jí)到 Java 的未來(lái)版本。397: 之前在JDK 15中進(jìn)行過(guò)預(yù)覽,JDK 16中二次預(yù)覽的密封類(lèi)和接口限制了可以擴(kuò)展或?qū)崿F(xiàn)它們的類(lèi)和接口。此計(jì)劃的目標(biāo)包括允許類(lèi)或接口的創(chuàng)建者控制負(fù)責(zé)實(shí)現(xiàn)它的代碼,提供比訪(fǎng)問(wèn)修飾符更聲明性的方式來(lái)限制超類(lèi)的使用,并通過(guò)提供模式分析基礎(chǔ)來(lái)支持模式匹配的未來(lái)發(fā)展。338: 孵化階段的矢量API(JDK將配備一個(gè)孵化器模塊),jdk.incubator.vector,以表達(dá)在可支持的CPU架構(gòu)上編譯為最佳硬件指令的矢量計(jì)算,以實(shí)現(xiàn)優(yōu)于等效標(biāo)量計(jì)算的性能。393: 孵化階段的外部存儲(chǔ)器訪(fǎng)問(wèn)API,允許Java程序安全的訪(fǎng)問(wèn)Java堆外的外部存儲(chǔ)器(包括本地、持久化介質(zhì)以及托管堆存儲(chǔ)器)。如上新特性前編號(hào)為JDK Enhancement Process的標(biāo)識(shí)符,詳見(jiàn)文末參考資料立即嘗鮮
瀏覽完17個(gè)新特性后,我都迫不及待的想嘗試一下JDK 16,以及其中一些對(duì)工程上有所幫助的特性了。那么先通過(guò)JDK官網(wǎng)進(jìn)行
JDK 16候選版下載(http://jdk.java.net/16/)
。由于要方便的在系統(tǒng)中針對(duì)多個(gè)JDK版本進(jìn)行切換,可以使用
jenv(https://github.com/jenv/jenv)
。我們把下載好的JDK16路徑添加到j(luò)env,在做如下設(shè)置即可使用。jenv add ${JDK16_Path}jenv global openjdk64-16
如果一切順利,那么查看JDK版本時(shí),會(huì)有類(lèi)似如下信息的返回。java -versionopenjdk version "16"2021-03-16OpenJDK Runtime Environment (build 16+36-2231)OpenJDK 64-Bit Server VM (build 16+36-2231, mixed mode, sharing)
如果你在使用較早的IDEA版本作為開(kāi)發(fā)工具,那么使用JDK 16運(yùn)行程序時(shí),可能收到如下的錯(cuò)誤:Cannot determine path to 'tools.jar' library for 16 (path/to/jdk-16) when running from IDEA, you should update to the latest version.
這是由于JDK9對(duì)Java運(yùn)行時(shí)做了重構(gòu),已刪除了rt.jar、tools.jar、dt.jar以及其它各種內(nèi)部JAR包。而在較早的開(kāi)發(fā)工具通常對(duì)這類(lèi)JAR包有依賴(lài),通過(guò)升級(jí)IDEA可以解決。到官網(wǎng)獲取一個(gè)
IDEA 2021.1 EAP預(yù)發(fā)版本新特性解讀
? 遷移到GitHub
早在2020年9月,OpenJDK已將Github上的jdk倉(cāng)庫(kù)作為JDK 16源碼的主讀取/寫(xiě)入倉(cāng)庫(kù)。隨著JDK 16的正式發(fā)布,這將是OpenJDK在Github上開(kāi)發(fā)完成的初代JDK版本。而促使將OpenJDK源代碼倉(cāng)庫(kù)從Mercurial遷移到Git的三個(gè)主要原因:版本控制系統(tǒng)元數(shù)據(jù),可用工具和可用托管的大小。版本控制元數(shù)據(jù)大小方面,轉(zhuǎn)換后的存儲(chǔ)庫(kù)的初始原型已顯示出版本控制元數(shù)據(jù)的大小顯著減少。例如,使用Git的jdk倉(cāng)庫(kù)的.git目錄大約為300MB,而使用Mercurial的.hg目錄大約為1.2GB。減少元數(shù)據(jù)可保留本地磁盤(pán)空間并減少克隆時(shí)間,同時(shí)減少傳輸?shù)臄?shù)據(jù)。
可用工具方面,與Mercurial相比,Git可用的工具更多。所有的文本編輯器都可以本地或通過(guò)插件實(shí)現(xiàn)Git集成。此外,幾乎所有的IDE都帶有Git集成,包括Eclipse、Visual Studio、IDEA。
可用托管方面,有許多選項(xiàng)可用于托管Git倉(cāng)庫(kù),無(wú)論是自托管還是作為服務(wù)托管。使用外部源碼托管提供程序的原因包括性能、與開(kāi)發(fā)人員進(jìn)行交互的Web API的訪(fǎng)問(wèn)權(quán)限控制 以及 蓬勃發(fā)展的社區(qū)。
OpenJDK遷移到Github之后,對(duì)于Java開(kāi)發(fā)者而言還是有不少的便利:如果是在IDEA下工作與學(xué)習(xí),clone好JDK 16源碼,打開(kāi)Project Structure (command+;),設(shè)置Project SDK為JDK 16,并設(shè)置Project language level到16。? 將JDK移植到Alpine Linux
在云原生時(shí)代,個(gè)人理解提升效率是第一原則:這樣就能保障系統(tǒng)水平伸縮夠快、問(wèn)題出現(xiàn)時(shí)回滾處理夠快。另外,出于降低成本考慮,更小的鏡像體積內(nèi)存占用會(huì)更小,分發(fā)時(shí)耗用的資源也更小。Alpine Linux就是與云原生的提升效率原則契合的一款獨(dú)立的非商業(yè)性的通用Linux發(fā)行版。其關(guān)注于安全性、簡(jiǎn)單性和資源效率,圍繞musl libc和busybox構(gòu)建。這使得它比傳統(tǒng)的GNU/Linux發(fā)行版更小。JDK移植到Alpine Linux后,將允許Tomcat、Jetty、Spring和其它流行的框架在其中工作。用戶(hù)可以創(chuàng)建一個(gè)更小的鏡像,以啟動(dòng)、運(yùn)行特定的應(yīng)用程序。提前準(zhǔn)備好Docker,我們先構(gòu)建一個(gè)Alpine Linux鏡像,然后添加JDK 16,最后運(yùn)行一個(gè)簡(jiǎn)單的Spring Boot程序來(lái)演示一下。# 獲取Alpine Linux鏡像docker pull alpine# 運(yùn)行鏡像docker run alpine echo'Hello Alpine!'
通過(guò)docker images命令查看鏡像大小會(huì)發(fā)現(xiàn),alpine在截止本文完成時(shí),鏡像大小僅僅只有5.6MB。相對(duì)于debian、ubuntu、centos等系統(tǒng)動(dòng)則幾十甚至上百M(fèi)B的鏡像來(lái)說(shuō),alpine可是真的??!REPOSITORY TAG IMAGE ID CREATED SIZEalpine latest 7731472c3f2a 7 weeks ago 5.61MB
? 添加JDK 16
OpenJDK通過(guò)使用jlink(
JEP 282:https://openjdk.java.net/jeps/282
)來(lái)減少Java運(yùn)行時(shí)的大小,我們可以從DockerHub上獲取鏡像:16-jdk-alpine(https://hub.docker.com/_/openjdk?tab=tags&page=1&name=16-jdk-alpine&ordering=last_updated)
。docker pull openjdk:16-jdk-alpine? 運(yùn)行Spring Boot
先準(zhǔn)備一個(gè)Spring Boot的FatJar程序,可以從Spring Boot官網(wǎng)獲取
Hello World!樣例程序(https://spring.io/guides/gs/rest-service/)
。創(chuàng)建一份Dockerfile,使用openjdk:16-jdk-alpine,并添加Spring Boot程序。FROM openjdk:16-jdk-alpineVOLUME /tmpARG JAR_FILEADD ${JAR_FILE} app.jarENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
? 構(gòu)建并運(yùn)行
# 構(gòu)建鏡像,設(shè)置JAR_FILE參數(shù)指向Spring Boot程序Jar包路徑docker build --build-argJAR_FILE=target/rest-service-0.0.1-SNAPSHOT.jar -t alpine-jdk16-app:latest . # 查看鏡像docker images # 根據(jù)鏡像,啟動(dòng)容器運(yùn)行# -d參數(shù) 后臺(tái)運(yùn)行# -p參數(shù) Spring Boot默認(rèn)端口8080,映射到容器端口8080docker run -d-p8080:8080 alpine-jdk16-app:latest # 查看容器運(yùn)行docker ps # 驗(yàn)證成功之后可以停止容器docker stop${CONTAINER_ID} # 訪(fǎng)問(wèn)應(yīng)用curl-w'\n' http://127.0.0.1:8080/greeting?name=jdk16
至此,通過(guò)Alpine Linux系統(tǒng)帶JDK 16運(yùn)行時(shí)的Spring Boot已經(jīng)啟動(dòng)并可以正常的訪(fǎng)問(wèn)了。Alpine系統(tǒng)JDK 16鏡像大小約為321MB。相比Oracle官方的Linux版本鏡像的467MB,減少30%+。記錄類(lèi)
從JDK 14開(kāi)始提供了Record記錄類(lèi)的預(yù)覽特性,這一特性將成為JDK 16的一項(xiàng)永久性特性。
Record記錄類(lèi)作為不可變數(shù)據(jù)的透明載體,其是為了回應(yīng)有關(guān)Java過(guò)于冗長(zhǎng)拘謹(jǐn)?shù)谋г埂?
此計(jì)劃的目標(biāo)包括設(shè)計(jì)一個(gè)表示簡(jiǎn)單值集合的面向?qū)ο蟮臉?gòu)造函數(shù),幫助開(kāi)發(fā)人員專(zhuān)注于對(duì)不可變數(shù)據(jù)的建模而不是擴(kuò)展行為,自動(dòng)實(shí)現(xiàn)數(shù)據(jù)驅(qū)動(dòng)的方法(例如 equals() 和 屬性的訪(fǎng)問(wèn)器)。
通過(guò)較新版IDEA可以創(chuàng)建此類(lèi)型:聲明Record記錄類(lèi)后,幾乎不需要添加額外的代碼,一組隱式聲明讓其代碼書(shū)寫(xiě)很簡(jiǎn)潔:public record Point(int x, int y) {}
Record記錄類(lèi)支持Local Classes特性,那么當(dāng)需要臨時(shí)使用Record的時(shí)候,就可以非常方便的定義與使用:ListfindTopMerchants(List merchants, int month) { // Local record record MerchantSales(Merchant merchant, double sales) {} // 使用MerchantSales Record類(lèi)臨時(shí)包裝merchant和sales,方便做處理。 return merchants.stream() .map(merchant ->new MerchantSales(merchant, computeSales(merchant, month))) .sorted((m1, m2) ->Double.compare(m2.sales(), m1.sales())) .map(MerchantSales::merchant) .collect(toList());}
Record記錄類(lèi)將可以代替Tuple、Pair等之前在JDK之外的工具庫(kù)提供的元組功能,在與下面將介紹的模式匹配特性配合,可使代碼將變得非常簡(jiǎn)潔。? 模式匹配
從JDK 14開(kāi)始引入了一種模式匹配的預(yù)覽特性,這一特性也將成為JDK 16的一項(xiàng)永久性特性。因此雖然JDK 16是個(gè)短期版本,也不妨礙我們?cè)谖磥?lái)的JDK版本中繼續(xù)使用模式匹配特性。模式匹配的現(xiàn)階段僅限于一種模式(類(lèi)型模式)和一種語(yǔ)言構(gòu)造(instanceof),但這只是完整特性的一部分。即便如此,我們也已經(jīng)獲得了一個(gè)顯著的好處:冗余的強(qiáng)制轉(zhuǎn)換消失了,消除了冗余的代碼,使更重要的代碼得到了更清晰的關(guān)注,同時(shí)消除了隱藏bug的地方。我們?cè)陂_(kāi)發(fā)中當(dāng)需要解析對(duì)象會(huì)用到類(lèi)似如下的方式if (obj instanceofString) { String s = (String) obj; ...}
if (obj instanceofString s) { // 通過(guò)使用模式匹配可以直接使用s局部變量 ...}
使用instanceof獲取對(duì)象類(lèi)型是一種條件提取形式,在獲得到對(duì)象類(lèi)型之后,總是要將對(duì)象強(qiáng)制轉(zhuǎn)換為該類(lèi)型。以前在instanceof之后必須進(jìn)行顯式類(lèi)型轉(zhuǎn)換,這是一種繁瑣的操作,而融合這些操作的好處不僅僅是為了簡(jiǎn)潔,它還消除了一個(gè)常見(jiàn)的錯(cuò)誤來(lái)源:在剪切和粘貼instanceof及強(qiáng)制轉(zhuǎn)換代碼,容易在修改了 instanceof的類(lèi)型之后忘記修改強(qiáng)制轉(zhuǎn)換類(lèi)型,這就給了漏洞一個(gè)藏身之處。通過(guò)instanceof的模式匹配消除了這個(gè)問(wèn)題,我們還可以消滅所有這種類(lèi)型的bug。另一個(gè)需要經(jīng)常的做此類(lèi)“先檢測(cè)后強(qiáng)制轉(zhuǎn)換”的地方是equals方法。publicbooleanequals(Object o) { if (!(o instanceof Point)) returnfalse; Point other = (Point) o; return x == other.x && y == other.y;}
publicbooleanequals(Object o) { return (o instanceof Point other) && x == other.x && y == other.y;}
這段代碼起到同樣的效果,但更簡(jiǎn)單直接,因?yàn)槲覀兛梢灾皇褂靡粋€(gè)復(fù)合布爾表達(dá)式來(lái)表達(dá)一個(gè)等價(jià)的條件,而不是使用控制流語(yǔ)句。模式匹配的綁定變量(如上代碼例子中 obj instanceof String s的s就是一個(gè)綁定變量)除了特殊的聲明位置以外,其作用域也與"普通"局部變量有所不同。if (a instanceof Point p) { // p is in scope ...} else { // p not in scope here} // p not in scope here if (b instanceof Point p) { // Sure! ...}
這樣特殊的作用域讓我們能夠在if-else的多分支情況下,自由的重新聲明綁定變量,也考慮未來(lái)在switch中的case也是如此便利。如:if (x instanceofInteger num) { ... }elseif (x instanceofLong num) { ... }elseif (x instanceofDouble num) { ... }
如果模式匹配可以消除Java代碼中99%的強(qiáng)制類(lèi)型轉(zhuǎn)換操作,那么它肯定會(huì)很流行。但還不僅限于此,隨著時(shí)間的推移,將會(huì)出現(xiàn)其他類(lèi)型的模式,它們可以進(jìn)行更復(fù)雜的條件提取,使用更復(fù)雜的方式來(lái)組合模式,以及提供其他可以使用模式的構(gòu)造:比如switch,甚至是catch,再加上目前已永久支持的Record類(lèi)以及在預(yù)覽中的密封類(lèi)等相關(guān)特性,模式匹配未來(lái)一定能夠大大簡(jiǎn)化我們編寫(xiě)的代碼。“JDK16有哪些新特性”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
文章題目:JDK16有哪些新特性
鏈接地址:
http://weahome.cn/article/pgcisi.html