點贊再看,動力無限。Hello world : ) 微信搜「 程序猿阿朗 」。
本文 Github.com/niumoo/JavaNotes 和 未讀代碼博客 已經收錄,有很多知識點和系列文章。
本文章屬於 Java 新特性教程 系列,已經收錄在 Github.com/niumoo/JavaNotes ,點個贊,不迷路。
自從 Oracle 調整了 Java 的版本發布節奏之后,Java 版本發布越來越快,雖然都說 Java 版本任他發,我用 Java 8,不過新版本的 Java 功能還是要學習一下的。
Java 13 早在 2019 年 9 月就已經發布,雖然不是長久支持版本,但是也帶來了不少新功能。
Java 13 官方下載:https://jdk.java.net/archive/
Java 13 官方文檔:http://openjdk.java.net/projects/jdk/13/
Java 13 新功能:
- JEP 350: 動態 CDS 存檔
- JEP 351: ZGC,歸還未使用的內存 (實驗性)
- JEP 353: 重新實現 Socket API
- JEP 354: Switch 表達式 (二次預覽)
- JEP 355: 文本塊 (預覽)
擴展:此文章屬於 Java 新特性教程 系列,會介紹 Java 每個版本的新功能,可以點擊瀏覽。
1. JEP 350 動態 CDS 存檔
JVM 啟動時有一步是需要在內存中加載類,而如果有多個 jar,加載第一個 jar 的速度是最慢的。這就延長了程序的啟動時間,為了減少這個時間,Java 10
引入了應用程序類數據共享(CDS)機制,它可以把你想共享的類共享在程序之間,使不同的 Java 進程之間共享這個類來減少這個類占用的空間以及加載速度。不過 Java 10 中使用這個功能的步驟比較繁瑣。
擴展閱讀:Java 10 新功能介紹
而 Java 13 中的 AppCDS,允許 Java 應用在程序執行結束時(如果 JVM 沒有崩潰)進行動態存檔;存儲的內容包括所有加載的應用類型類和使用的類庫,這些存儲的類庫本來並不存在於默認的 CDS 存檔中。
使用這個功能非常簡單,只需要在程序啟動時增加啟動參數 。
# ArchiveClassesAtExit,程序結束時動態存檔
bin/java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
# SharedArchiveFile,使用指定存檔啟動
bin/java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello
2. JEP 351: ZGC,歸還未使用的內存 (實驗性)
在 Java 13 之前,ZGC 雖然在清理內存時導致的停頓時間非常少,但是即使內存已經長時間沒有使用,ZGC 也不會將內存返還給操作系統,這對那些十分關注內存占用的應用程序非常不友好。
比如:
-
資源按使用量付費的雲上容器環境。
-
應用雖然長時間閑置,但是占用了內存,導致運行的其他程序內存緊張。
而新增的這個功能,可以讓 ZGC 歸還長時間沒有使用的內存給操作系統,這對某些用戶來說十分友好。
3. JEP 353: 重新實現 Socket API
java.net.Socket
和 java.net.ServerSocket
類早在 Java 1.0 時就已經引入了,它們的實現的 Java 代碼和 C 語言代碼的混合,維護和調試都十分不易;而且這個實現還存在並發問題,有時候排查起來也很困難。
因此,在 Java 13 中引入了新的實現方式,使用了新的實現 NioSocketImpl
來代替老舊的 PlainSocketImpl
實現。雖然功能相同,但是老的方式在當前以及未來幾個版本內不會刪除,用戶隨時可以通過 -Djdk.net.usePlainSocketImpl
參數切換回老的實現方式,以兼容意外情況。
編寫一個測試類可以發現這個變化。
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Test {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(8000)){
boolean running = true;
while(running){
Socket clientSocket = serverSocket.accept();
//do something with clientSocket
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用 Java 13 運行,通過參數 -XX:+TraceClassLoading
追蹤加載的類,日志中可以看到 NioSocketImpl
。
➜ develop ./jdk-13.0.2.jdk/Contents/Home/bin/java -XX:+TraceClassLoading Test.java | grep SocketImpl
[0.699s][info ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.699s][info ][class,load] java.net.SocketImpl$$Lambda$173/0x0000000800c37440 source: java.net.SocketImpl
[0.702s][info ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.702s][info ][class,load] sun.nio.ch.NioSocketImpl source: jrt:/java.base
[0.713s][info ][class,load] sun.nio.ch.NioSocketImpl$FileDescriptorCloser source: jrt:/java.base
但在 Java 12 並不是 NioSocketImpl
。
➜ develop ./jdk-12.0.2.jdk/Contents/Home/bin/java -XX:+TraceClassLoading Test.java | grep SocketImpl
[0.665s][info ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.665s][info ][class,load] java.net.AbstractPlainSocketImpl source: jrt:/java.base
[0.665s][info ][class,load] java.net.PlainSocketImpl source: jrt:/java.base
[0.665s][info ][class,load] java.net.SocksSocketImpl source: jrt:/java.base
[0.666s][info ][class,load] java.net.AbstractPlainSocketImpl$1 source: jrt:/java.base
4. JEP 354: Switch 表達式 (二次預覽)
你為什么不願意使用使用 switch
表達式?我想其中一個原因應該是, switch
表達式的代碼不夠美觀優雅,甚至有些啰嗦。比如像下面的例子。
package com.wdbyte;
public class Java13Switch {
public static void main(String[] args) {
//通過傳入月份,輸出月份所屬的季節
System.out.println(switchJava12Before("march"));
}
public static String switchJava12Before(String month) {
String reuslt = null;
switch (month) {
case "march":
case "april":
case "may":
reuslt = "春天";
break;
case "june":
case "july":
case "august":
reuslt = "夏天";
break;
case "september":
case "october":
case "november":
reuslt = "秋天";
break;
case "december":
case "january":
case "february":
reuslt = "冬天";
break;
}
return reuslt;
}
}
而在 Java 12 中,已經對 switch
進行了改進,使之可以使用 cast L ->
表達式進行操作,且可以具有返回值,這樣代碼就更加美觀使用了,不過這在 Java 12 中是一個預覽功能。
// 通過傳入月份,輸出月份所屬的季節
public static String switchJava12(String month) {
return switch (month) {
case "march", "april", "may" -> "春天";
case "june", "july", "august" -> "夏天";
case "september", "october", "november" -> "秋天";
case "december", "january", "february" -> "冬天";
default -> "month erro";
};
}
而現在,在 Java 13 中,又對 switch
表達式進行了增強,增加了yield
關鍵詞用於返回值,相比 break
,語義更加明確了。
public static String switchJava13(String month) {
return switch (month) {
case "march", "april", "may":
yield "春天";
case "june", "july", "august":
yield "夏天";
case "september", "october", "november":
yield "秋天";
case "december", "january", "february":
yield "冬天";
default:
yield "month error";
};
}
5. JEP 355: 文本塊 (預覽)
在這之前,如果我們把一個 JSON 賦值給字符串:
String content = "{\n"
+ " \"upperSummary\": null,\n"
+ " \"sensitiveTypeList\": null,\n"
+ " \"gmtModified\": \"2011-08-05 10:50:09\",\n"
+ " \"lowerGraph\": null,\n"
+ " \"signature\": \"\",\n"
+ " \"appName\": \"xxx\",\n"
+ " \"lowerSummary\": null,\n"
+ " \"gmtCreate\": \"2011-08-05 10:50:09\",\n"
+ " \"type\": \"CALL\",\n"
+ " \"name\": \"xxxx\",\n"
+ " \"subType\": \"yyy\",\n"
+ " \"id\": 1,\n"
+ " \"projectId\": 1,\n"
+ " \"status\": 1\n"
+ "}";
終於不用寫丑陋的長字符串了,從 Java 13 開始你可以使用文本塊的方式定義字符串了。
String content2 = """
{
"upperSummary": null,
"sensitiveTypeList": null,
"gmtModified": "2011-08-05 10:50:09",
"lowerGraph": null,
"signature": "",
"appName": "xxx",
"lowerSummary": null,
"gmtCreate": "2011-08-05 10:50:09",
"type": "CALL",
"name": "xxxx",
"subType": "yyy",
"id": 1,
"projectId": 1,
"status": 1
}
""";
不過這是一個預覽功能,如果你要是在 Java 13 中使用需要手動開啟預覽功能,這個功能在 Java 15 中正式發布。
如果你想嘗試,可以去下載最新版了,玩的開心。
參考
- http://openjdk.java.net/projects/jdk/13/
- https://nipafx.dev/java-application-class-data-sharing/
- https://www.wdbyte.com/2020/02/jdk/jdk12-feature/
- https://mkyong.com/java/what-is-new-in-java-13/
- Java 新特性教程
相關閱讀
- Java 12 新特性介紹
- Java 11 新特性介紹
- Java 10 新特性介紹
- Java 9 新特性介紹
- Java 8 函數接口 UnaryOperator
- Java 8 函數接口 BiPredicate
- Java 8 函數接口 BiFunction
- Java 8 函數接口 Supplier
- Java 8 函數接口 Predicate
- Java 8 函數接口 Function
- Java 8 新特性 - forEach 遍歷
- Java 8 新特性 - LocalDate、LocalDateTime 時間處理介紹
- Java 8 新特性 - 使用 Optional 優雅的處理空指針
- Java 8 新特性 - Lambda 表達式、函數接口了解一下
- Java 8 新特性 - 超強的 Stream 流操作姿勢還不學習一下
- Java 7 新特性 - 和低效 IO 說再見,Files,Paths,Path 文件操作介紹
- Java 7 新特性 - 新特性 - 快來補一波 Java 7 語法特性
<完>
Hello world : ) 我是阿朗,一線技術工具人,認認真真寫文章。
點贊的個個都是人才,不僅長得帥氣好看,說話還好聽。
文章持續更新,可以關注公眾號「 程序猿阿朗 」或訪問「未讀代碼博客 」。
回復【資料】有我准備的各系列知識點和必看書籍。
本文 Github.com/niumoo/JavaNotes 已經收錄,有很多知識點和系列文章,歡迎Star。