Java 13 於2019年9月17日正式發布供生產使用。由於每6個月釋出一次的版本週期,Java 13 中沒有太多針對開發者的特定功能。
Java 13功能
一些重要的Java 13功能包括:
- 文本區塊 – JEP 355
- String類中的新方法用於文本區塊
- Switch表達式增強 – JEP 354
- 重新實現遺留Socket API – JEP 353
- 動態CDS存檔 – JEP 350
- ZGC:未使用內存的取消 – JEP 351
- FileSystems.newFileSystem() 方法
- 支援Unicode 12.1
- 具有命名空間支援的DOM和SAX工廠
如何啟用預覽功能
Switch表達式和文本區塊是預覽功能。因此,您需要在項目中啟用預覽功能設置。如果您從命令行運行Java程序,可以使用--enable-preview
選項啟用它。您可以使用此選項啟動帶有啟用預覽功能的JShell。
$ jshell --enable-preview
$ java --enable-preview --source 13 Test.java
如果您使用Eclipse IDE,可以從項目Java編譯器設置中啟用預覽功能。

1. 文本區塊 – JEP 355
這是一個預覽功能。它允許我們輕鬆創建多行字符串。多行字符串必須寫在一對三重雙引號內。使用文本區塊創建的字符串對象沒有其他屬性。這是一種更容易創建多行字符串的方法。我們不能使用文本區塊創建單行字符串。開始的三重雙引號必須後跟一個行終止符。
package com.journaldev.java13.examples;
public class TextBlockString {
/**
* JEP 355: Preview Feature
*/
@SuppressWarnings("preview")
public static void main(String[] args) {
String textBlock = """
Hi
Hello
Yes""";
String str = "Hi\nHello\nYes";
System.out.println("Text Block String:\n" + textBlock);
System.out.println("Normal String Literal:\n" + str);
System.out.println("Text Block and String Literal equals() Comparison: " + (textBlock.equals(str)));
System.out.println("Text Block and String Literal == Comparison: " + (textBlock == str));
}
}
輸出:
Text Block String:
Hi
Hello
Yes
Normal String Literal:
Hi
Hello
Yes
Text Block and String Literal equals() Comparison: true
Text Block and String Literal == Comparison: true
在我們的Java程序中,這對於輕鬆創建HTML和JSON字符串很有用。
String textBlockHTML = """
<html>
<head>
<link href='/css/style.css' rel='stylesheet' />
</head>
<body>
<h1>Hello World</h1>
</body>
</html>""";
String textBlockJSON = """
{
"name":"Pankaj",
"website":"JournalDev"
}""";
2. 文本區塊中String類的新方法
String類中有三個與文本區塊功能相關的新方法。
- formatted(Object… args):它類似於String的format()方法。它添加了支持使用文本區塊進行格式化的功能。
- stripIndent():用於刪除文本區塊中每行開始和結尾的偶然空格字符。此方法由文本區塊使用,並保留內容的相對縮進。
- translateEscapes(): 返回一個字串,其值是這個字串,其中的轉義序列被翻譯,就像在字串文字中一樣。
package com.journaldev.java13.examples;
public class StringNewMethods {
/***
* New methods are to be used with Text Block Strings
* @param args
*/
@SuppressWarnings("preview")
public static void main(String[] args) {
String output = """
Name: %s
Phone: %d
Salary: $%.2f
""".formatted("Pankaj", 123456789, 2000.5555);
System.out.println(output);
String htmlTextBlock = "<html> \n"+
"\t<body>\t\t \n"+
"\t\t<p>Hello</p> \t \n"+
"\t</body> \n"+
"</html>";
System.out.println(htmlTextBlock.replace(" ", "*"));
System.out.println(htmlTextBlock.stripIndent().replace(" ", "*"));
String str1 = "Hi\t\nHello' \" /u0022 Pankaj\r";
System.out.println(str1);
System.out.println(str1.translateEscapes());
}
}
輸出:
Name: Pankaj
Phone: 123456789
Salary: $2000.56
<html>***
<body> *
<p>Hello</p>** *
</body>*
</html>
<html>
<body>
<p>Hello</p>
</body>
</html>
Hi
Hello' " /u0022 Pankaj
Hi
Hello' " /u0022 Pankaj
3. Switch Expressions Enhancements – JEP 354
Switch expressions were added as a preview feature in Java 12 release. It’s almost same in Java 13 except that the “break” has been replaced with “yield” to return a value from the case statement.
package com.journaldev.java13.examples;
/**
* JEP 354: Switch Expressions
* https://openjdk.java.net/jeps/354
* @author pankaj
*
*/
public class SwitchEnhancements {
@SuppressWarnings("preview")
public static void main(String[] args) {
int choice = 2;
switch (choice) {
case 1:
System.out.println(choice);
break;
case 2:
System.out.println(choice);
break;
case 3:
System.out.println(choice);
break;
default:
System.out.println("integer is greater than 3");
}
// from java 13 onwards - multi-label case statements
switch (choice) {
case 1, 2, 3:
System.out.println(choice);
break;
default:
System.out.println("integer is greater than 3");
}
// switch expressions, use yield to return, in Java 12 it was break
int x = switch (choice) {
case 1, 2, 3:
yield choice;
default:
yield -1;
};
System.out.println("x = " + x);
}
enum Day {
SUN, MON, TUE
};
@SuppressWarnings("preview")
public String getDay(Day d) {
String day = switch (d) {
case SUN -> "Sunday";
case MON -> "Monday";
case TUE -> "Tuesday";
};
return day;
}
}
4. Reimplement the Legacy Socket API – JEP 353
The underlying implementation of the java.net.Socket and java.net.ServerSocket APIs have been rewritten. The new implementation, NioSocketImpl, is a drop-in replacement for PlainSocketImpl. It uses java.util.concurrent locks rather than synchronized methods. If you want to use the legacy implementation, use the java option -Djdk.net.usePlainSocketImpl.
5. 動態 CDS 存檔 – JEP 350
此 JEP 擴展了在 Java 10 中引入的類數據共享功能。現在,創建 CDS 存檔並使用它變得更加容易。
$ java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar
$ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar
6. ZGC:釋放未使用的內存 – JEP 351
此 JEP 已增強 ZGC,以將未使用的堆內存返回給操作系統。Z 垃圾收集器是在 Java 11 中引入的。它在堆內存清理之前添加了短暫的暫停時間。但是,未使用的內存未返回給操作系統是一個問題,特別是對於像 IoT 和微控制器這樣的記憶體占用小的設備。現在,它已經增強,可以將未使用的內存返回給操作系統。
7. FileSystems.newFileSystem() 方法
FileSystems 類別新增了三種新的方法,以便更容易地使用檔案系統提供者,該提供者將檔案的內容視為檔案系統。
- newFileSystem(Path)
- newFileSystem(Path, Map<String, ?>)
- newFileSystem(Path, Map<String, ?>, ClassLoader)
8. 具有命名空間支持的 DOM 和 SAX 工廠
有新的方法來實例化具有命名空間支持的 DOM 和 SAX 工廠。
- newDefaultNSInstance()
- newNSInstance()
- newNSInstance(String factoryClassName, ClassLoader classLoader)
//java 13 之後
DocumentBuilder db = DocumentBuilderFactory.newDefaultNSInstance().newDocumentBuilder();
// 在 java 13 之前
DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
結論
看來 Java 每六個月的發布都運作良好。 沒有太多針對開發人員的特定功能,但整體來說是一個很棒的發布版本。 很高興看到期待已久的文本塊字符串支持。
參考資料
Source:
https://www.digitalocean.com/community/tutorials/java-13-features