我有點(diǎn)想用 JDK 21 了~
共 18667字,需瀏覽 38分鐘
·
2024-06-19 10:43
來源:juejin.cn/post/7376444924424241162
?? 歡迎加入小哈的星球 ,你將獲得: 專屬的項(xiàng)目實(shí)戰(zhàn) / Java 學(xué)習(xí)路線 / 一對一提問 / 學(xué)習(xí)打卡 / 每月贈書
新項(xiàng)目:仿小紅書(微服務(wù)架構(gòu))正在更新中... 。全棧前后端分離博客項(xiàng)目 2.0 版本完結(jié)啦, 演示鏈接:http://116.62.199.48/ 。全程手摸手,后端 + 前端全棧開發(fā),從 0 到 1 講解每個(gè)功能點(diǎn)開發(fā)步驟,1v1 答疑,直到項(xiàng)目上線。目前已更新了287小節(jié),累計(jì)45w+字,講解圖:2008張,還在持續(xù)爆肝中.. 后續(xù)還會上新更多項(xiàng)目,目標(biāo)是將Java領(lǐng)域典型的項(xiàng)目都整一波,如秒殺系統(tǒng), 在線商城, IM即時(shí)通訊,Spring Cloud Alibaba 等等,戳我加入學(xué)習(xí),已有1600+小伙伴加入(早鳥價(jià)超低)
-
DK17語法新特性 -
文本塊 -
NullPointerException增強(qiáng) -
Records -
全新的switch表達(dá)式 -
私有接口方法 -
模式匹配 -
集合類的工廠方法 -
其他的新特性 -
新的String方法 -
Stream API的增強(qiáng) -
全新的HttpClient -
jshell -
java命令直接執(zhí)行java文件 -
ZGC -
小結(jié)一下
JDK 版本升級的非???,現(xiàn)在已經(jīng)到 JDK20 了。JDK 版本雖多,但應(yīng)用最廣泛的還得是 JDK8,正所謂“他發(fā)任他發(fā),我用Java8”。
其實(shí)我也不太想升級 JDK 版本,感覺投入高,收益小,不過有一次我看到了一些使用 JDK17 新語法寫的代碼,讓我改變了對升級 JDK 的看法,因?yàn)檫@些新語法我確實(shí)想用!
廢話不多說,上代碼!
DK17語法新特性
文本塊
這個(gè)更新非常實(shí)用。在沒有這個(gè)特性之前,編寫長文本非常痛苦。雖然IDEA等集成開發(fā)工具可以自動處理,但最終效果仍然丑陋,充滿拼接符號?,F(xiàn)在,通過字符串塊,我們可以輕松編寫JSON、HTML、SQL等內(nèi)容,效果更清爽。這個(gè)新特性值得五顆星評價(jià),因?yàn)樗屛覀冎恍桕P(guān)注字符串本身,而無需關(guān)心拼接操作。
原來的寫法
/**
* 使用JDK8返回HTML文本
*
* @return 返回HTML文本
*/
public static final String getHtmlJDK8() {
return "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>";
}
新的寫法
/**
* 使用JDK17返回HTML文本
* @return 返回HTML文本
*/
public static final String getHtmlJDK17() {
return """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
}
推薦指數(shù):??????????
NullPointerException增強(qiáng)
這一功能非常強(qiáng)大且實(shí)用,相信每位Java開發(fā)者都期待已久。空指針異常(NPE)一直是Java程序員的痛點(diǎn),因?yàn)閳?bào)錯信息無法直觀地指出哪個(gè)對象為空,只拋出一個(gè)NullPointerException和一堆堆棧信息,定位問題耗時(shí)且麻煩。尤其在遇到喜歡級聯(lián)調(diào)用的代碼時(shí),逐行排查更是令人頭疼。如果在測試環(huán)境中,可能還需通過遠(yuǎn)程調(diào)試查明空對象,費(fèi)時(shí)費(fèi)力。為此,阿里的編碼規(guī)范甚至不允許級聯(lián)調(diào)用,但這并不能徹底解決問題。Java17終于在這方面取得了突破,提供了更詳細(xì)的空指針異常信息,幫助開發(fā)者迅速定位問題源頭。
public static void main(String[] args) {
try {
//簡單的空指針
String str = null;
str.length();
} catch (Exception e) {
e.printStackTrace();
}
try {
//復(fù)雜一點(diǎn)的空指針
var arr = List.of(null);
String str = (String)arr.get(0);
str.length();
} catch (Exception e) {
e.printStackTrace();
}
}
運(yùn)行結(jié)果
推薦指數(shù):??????????
Records
在Java中,POJO對象(如DO、PO、VO、DTO等)通常包含成員變量及相應(yīng)的Getter和Setter方法。盡管可以通過工具或IDE生成這些代碼,但修改和維護(hù)仍然麻煩。Lombok插件為此出現(xiàn),能夠在編譯期間自動生成Getter、Setter、hashcode、equals和構(gòu)造函數(shù)等代碼,使用起來方便,但對團(tuán)隊(duì)有依賴要求。為此,Java引入了標(biāo)準(zhǔn)解決方案:Records。它通過簡潔的語法定義數(shù)據(jù)類,大大簡化了POJO類的編寫,如下所示。雖然hashcode和equals方法仍需手動編寫,但I(xiàn)DE能夠自動生成。這一特性有效解決了模板代碼問題,提升了代碼整潔度和可維護(hù)性。
package com.xttblog.jdk17;
/**
* 3星
*
* @param stuId 學(xué)生ID
* @param stuName 學(xué)生名稱
* @param stuAge 學(xué)生年齡
* @param stuGender 學(xué)生性別
* @param stuEmail 學(xué)生郵箱
*/
public record StudentRecord(Long stuId,
String stuName,
int stuAge,
String stuGender,
String stuEmail) {
public StudentRecord {
System.out.println("構(gòu)造函數(shù)");
}
public static void main(String[] args) {
StudentRecord record = new StudentRecord(1L, "張三", 16, "男", "[email protected]");
System.out.println(record);
}
}
推薦指數(shù):????????
全新的switch表達(dá)式
有人可能問了,Java語言不早已支持switch了嘛,有什么好提的?講真,這次的提升還真有必要好好地來聊一聊了。在Java12的時(shí)候就引入了switch表達(dá)式,注意這里是表達(dá)式,而不是語句,原來的switch是語句。如果不清楚兩者的區(qū)別的話,最好先去了解一下。主要的差別就是就是表達(dá)式有返回值,而語句則沒有。再配合模式匹配,以及yield和“->”符號的加入,全新的switch用起來爽到飛起來。
package com.xttblog.jdk17;
public class SwitchDemo {
/**
* 在JDK8中獲取switch返回值方式
*
* @param week
* @return
*/
public int getByJDK8(Week week) {
int i = 0;
switch (week) {
case MONDAY, TUESDAY:
i = 1;
break;
case WEDNESDAY:
i = 3;
break;
case THURSDAY:
i = 4;
break;
case FRIDAY:
i = 5;
break;
case SATURDAY:
i = 6;
break;
case SUNDAY:
i = 7;
break;
default:
i = 0;
break;
}
return i;
}
/**
* 在JDK17中獲取switch返回值
*
* @param week
* @return
*/
public int getByJDK17(Week week) {
// 1, 現(xiàn)在的switch變成了表達(dá)式,可以返回值了,而且支持yield和->符號來返回值
// 2, 再也不用擔(dān)心漏寫了break,而導(dǎo)致出問題了
// 3, case后面支持寫多個(gè)條件
return switch (week) {
case null -> -1;
case MONDAY -> 1;
case TUESDAY -> 2;
case WEDNESDAY -> 3;
case THURSDAY -> {yield 4;}
case FRIDAY -> 5;
case SATURDAY, SUNDAY -> 6;
default -> 0;
};
}
private enum Week {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
}
推薦指數(shù):????????
私有接口方法
從Java8開始,允許在interface里面添加默認(rèn)方法,其實(shí)當(dāng)時(shí)就有些小困惑,如果一個(gè)default方法體很大怎么辦,拆到另外的類去寫嗎?實(shí)在有些不太合理,所以在Java17里面,如果一個(gè)default方法體很大,那么可以通過新增接口私有方法來進(jìn)行一個(gè)合理的拆分了,為這個(gè)小改進(jìn)點(diǎn)個(gè)贊。
public interface PrivateInterfaceMethod {
/**
* 接口默認(rèn)方法
*/
default void defaultMethod() {
privateMethod();
}
// 接口私有方法,在Java8里面是不被允許的,不信你試試
private void privateMethod() {
}
}
推薦指數(shù):??????
模式匹配
在JDK 17中,模式匹配主要用于instanceof表達(dá)式。模式匹配增強(qiáng)了instanceof的語法和功能,使類型檢查和類型轉(zhuǎn)換更加簡潔和高效。在傳統(tǒng)的Java版本中,我們通常使用instanceof結(jié)合類型轉(zhuǎn)換來判斷對象類型并進(jìn)行處理,這往往會導(dǎo)致冗長的代碼。
原來的寫法
/**
* 舊式寫法
*
* @param value
*/
public void matchByJDK8(Object value) {
if (value instanceof String) {
String v = (String)value;
System.out.println("遇到一個(gè)String類型" + v.toUpperCase());
} else if (value instanceof Integer) {
Integer v = (Integer)value;
System.out.println("遇到一個(gè)整型類型" + v.longValue());
}
}
新的寫法
/**
* 轉(zhuǎn)換并申請了一個(gè)新的變量,極大地方便了代碼的編寫
*
* @param value
*/
public void matchByJDK17(Object value) {
if (value instanceof String v) {
System.out.println("遇到一個(gè)String類型" + v.toUpperCase());
} else if (value instanceof Integer v) {
System.out.println("遇到一個(gè)整型類型" + v.longValue());
}
}
推薦指數(shù):????????
集合類的工廠方法
在Java8的年代,即便創(chuàng)建一個(gè)很小的集合,或者固定元素的集合都是比較麻煩的,為了簡潔一些,有時(shí)我甚至?xí)胍恍┮蕾嚒?/p>
原來的寫法
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c"
新的寫法
Set<String> set = Set.of("a", "b", "c");
推薦指數(shù):??????????
其他的新特性
新的String方法
-
repeat:重復(fù)生成字符串 -
isBlank:不用在引入第三方庫就可以實(shí)現(xiàn)字符串判空了 -
strip:去除字符串兩邊的空格,支持全角和半角,之前的trim只支持半角 -
lines:能根據(jù)一段字符串中的終止符提取出行為單位的流 -
indent:給字符串做縮進(jìn),接受一個(gè)int型的輸入 -
transform:接受一個(gè)轉(zhuǎn)換函數(shù),實(shí)現(xiàn)字符串的轉(zhuǎn)換
Stream API的增強(qiáng)
增加takeWhile, dropWhile, ofNullable, iterate以及toList的API,越來越像一些函數(shù)式語言了。用法舉例如下。
// takeWhile 順序返回符合條件的值,直到條件不符合時(shí)即終止繼續(xù)判斷,
// 此外toList方法的加入,也大大減少了節(jié)省了代碼量,免去了調(diào)用collect(Collectors::toList)方法了
List<Integer> list = Stream.of(2,2,3,4,5,6,7,8,9,10)
.takeWhile(i->(i%2==0)).toList(); // 返回2, 2
// dropWhile 順序去掉符合條件的值,直到條件不符合時(shí)即終止繼續(xù)判斷
List<Integer> list1 = Stream.of(2,2,3,4,5,6,7,8,9,10)
.dropWhile(i->(i%2==0)).toList(); //返回3, 4, 5, 6, 7, 8, 9, 10
// ofNullable,支持傳入空流,若沒有這個(gè)且傳入一個(gè)空流,那么將會拋NPE
var nullStreamCount = Stream.ofNullable(null).count(); //返回0
// 以下兩行都將輸出0到9
Stream.iterate(0, n -> n < 10, n -> n + 1).forEach(x -> System.out.println(x));
Stream.iterate(0, n -> n + 1).limit(10).forEach(x -> System.out.println(x));
全新的HttpClient
這個(gè)API首次出現(xiàn)在9之中,不過當(dāng)時(shí)并非是一個(gè)穩(wěn)定版本,在Java11中正式得到發(fā)布,所以在Java17里面可以放心地進(jìn)行使用。原來的JDK自帶的Http客戶端真的非常難用,這也就給了很多像okhttp、restTemplate、Apache的HttpClient和feign這樣的第三方庫極大的發(fā)揮空間,幾乎就沒有人愿意去用原生的Http客戶端的。但現(xiàn)在不一樣了,感覺像是新時(shí)代的API了。FluentAPI風(fēng)格,處處充滿了現(xiàn)代風(fēng)格,用起來也非常地方便,再也不用去依賴第三方的包了,就兩個(gè)字,清爽。
// 同步請求
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_1_1)
.followRedirects(Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(20))
.proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
.authenticator(Authenticator.getDefault())
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
// 異步請求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://foo.com/"))
.timeout(Duration.ofMinutes(2))
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofFile(Paths.get("file.json")))
.build();
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
jshell
在新的JDK版本中,支持直接在命令行下執(zhí)行java程序,類似于python的交互式REPL。簡而言之,使用 JShell,你可以輸入代碼片段并馬上看到運(yùn)行結(jié)果,然后就可以根據(jù)需要作出調(diào)整,這樣在驗(yàn)證一些簡單的代碼的時(shí)候,就可以通過jshell得到快速地驗(yàn)證,非常方便。
java命令直接執(zhí)行java文件
在現(xiàn)在可以直接通過執(zhí)行“java xxx.java”,即可運(yùn)行該java文件,無須先執(zhí)行javac,然后再執(zhí)行java,是不是又簡單了一步。
ZGC
在ParallelOldGC、CMS和G1之后,JDK 11引入了全新的ZGC(Z Garbage Collector)。這個(gè)名字本身就顯得很牛。官方宣稱ZGC的垃圾回收停頓時(shí)間不超過10ms,能支持高達(dá)16TB的堆空間,并且停頓時(shí)間不會隨著堆的增大而增加。那么,ZGC到底解決了什么問題?Oracle官方介紹它是一個(gè)可伸縮的低延遲垃圾回收器,旨在降低停頓時(shí)間,盡管這可能會導(dǎo)致吞吐量的降低。不過,通過橫向擴(kuò)展服務(wù)器可以解決吞吐量問題。官方已建議ZGC可用于生產(chǎn)環(huán)境,這無疑將成為未來的主流垃圾回收器。要了解更多,請參閱官方文檔
https://docs.oracle.com/en/java/javase/17/gctuning/z-garbage-collector.html#GUID-9957D441-A99A-4CF5-9522-393E6DE7D898。
小結(jié)一下
作為程序員,持續(xù)學(xué)習(xí)和充電非常重要。隨著Java8即將停止免費(fèi)官方支持,越來越多的項(xiàng)目將轉(zhuǎn)向Java17,包括大名鼎鼎的Spring Boot 3.0,它在2022年1月20日發(fā)布的第一個(gè)里程碑版本(M1)正是基于Java17構(gòu)建的。該項(xiàng)目依賴的所有組件也將快速升級,未來如果想利用某些新特性,在Java8下將無法通過編譯,到這時(shí)候再換就真的晚了... ...
?? 歡迎加入小哈的星球 ,你將獲得: 專屬的項(xiàng)目實(shí)戰(zhàn) / Java 學(xué)習(xí)路線 / 一對一提問 / 學(xué)習(xí)打卡 / 每月贈書
新項(xiàng)目:仿小紅書(微服務(wù)架構(gòu))正在更新中... 。全棧前后端分離博客項(xiàng)目 2.0 版本完結(jié)啦, 演示鏈接:http://116.62.199.48/ 。全程手摸手,后端 + 前端全棧開發(fā),從 0 到 1 講解每個(gè)功能點(diǎn)開發(fā)步驟,1v1 答疑,直到項(xiàng)目上線。目前已更新了287小節(jié),累計(jì)45w+字,講解圖:2008張,還在持續(xù)爆肝中.. 后續(xù)還會上新更多項(xiàng)目,目標(biāo)是將Java領(lǐng)域典型的項(xiàng)目都整一波,如秒殺系統(tǒng), 在線商城, IM即時(shí)通訊,Spring Cloud Alibaba 等等,戳我加入學(xué)習(xí),已有1600+小伙伴加入(早鳥價(jià)超低)
2. Spring Cloud + Nacos + 負(fù)載均衡器實(shí)現(xiàn)全鏈路灰度發(fā)布實(shí)戰(zhàn)
最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。
獲取方式:點(diǎn)“在看”,關(guān)注公眾號并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。
PS:因公眾號平臺更改了推送規(guī)則,如果不想錯過內(nèi)容,記得讀完點(diǎn)一下“在看”,加個(gè)“星標(biāo)”,這樣每次新文章推送才會第一時(shí)間出現(xiàn)在你的訂閱列表里。
點(diǎn)“在看”支持小哈呀,謝謝啦
