Java SE 21 新增特性
作者:Grey
原文地址:
原始碼
映象倉庫: GitCode:java_new_features
Record Patterns
該功能首次在 Java SE 19 中預覽,在Java SE 20中釋出第二次預覽版,在此版本中成為永久性功能。這意味著它可以在任何為 Java SE 21 編譯的程式中使用,而無需啟用預覽功能。
示例程式碼如下
package git.snippets.jdk21;
/**
* record 模式匹配增強
* 無須增加 --enable-preview引數
*
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2023/09/25
* @since 21
*/
public class RecordTest {
public static void main(String[] args) {
Points points = new Points(1, 2);
Line line = new Line(new Points(1, 2), new Points(3, 4));
printPoints(points);
printLine(line);
}
private static void printPoints(Object object) {
if (object instanceof Points(int x, int y)) {
System.out.println("jdk 19 object is a position, x = " + x + ", y = " + y);
}
if (object instanceof Points points) {
System.out.println("pre jdk 19 object is a position, x = " + points.x()
+ ", y = " + points.y());
}
switch (object) {
case Points position -> System.out.println("pre jdk 19 object is a position, x = " + position.x()
+ ", y = " + position.y());
default -> throw new IllegalStateException("Unexpected value: " + object);
}
switch (object) {
case Points(int x, int y) -> System.out.println(" jdk 19 object is a position, x = " + x
+ ", y = " + y);
default -> throw new IllegalStateException("Unexpected value: " + object);
}
}
public static void printLine(Object object) {
if (object instanceof Line(Points(int x1, int y1), Points(int x2, int y2))) {
System.out.println("object is a path, x1 = " + x1 + ", y1 = " + y1
+ ", x2 = " + x2 + ", y2 = " + y2);
}
switch (object) {
case Line(Points(int x1, int y1), Points(int x2, int y2)) ->
System.out.println("object is a path, x1 = " + x1 + ", y1 = " + y1
+ ", x2 = " + x2 + ", y2 = " + y2);
// other cases ...
default -> throw new IllegalStateException("Unexpected value: " + object);
}
}
}
record Points(int x, int y) {
}
record Line(Points from, Points to) {
}
Switch 匹配增強
該功能首次在 Java SE 17 中預覽,在在此版本中成為永久性功能。這意味著它可以在任何為 Java SE 21 編譯的程式中使用,而無需啟用預覽功能。
package git.snippets.jdk21;
/**
* switch型別增強匹配
* 無須增加預覽引數
*
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2023/09/25
* @since 21
*/
public class SwitchMatchTest {
public static void main(String[] args) {
switchMatch(3);
switchMatch("HELLO");
switchMatch("hello world");
switchMatch(null);
}
static void switchMatch(Object obj) {
switch (obj) {
case String s when s.length() > 5 -> System.out.println(s.toUpperCase());
case String s -> System.out.println(s.toLowerCase());
case Integer i -> System.out.println(i * i);
case null -> System.out.println("null obj");
default -> {
}
}
}
}
String template(預覽功能)
作為本版本的預覽功能推出。字串模板是對 Java 現有字串字面量和文字塊的補充,它將字面文字與嵌入式表示式和模板處理器結合起來,從而產生專門的結果。
在 Java SE 21之前,字串的拼接可以用下述三種方式
public static void stringTestBefore21() {
int a = 1;
int b = 2;
String concatenated = a + " times " + b + " = " + a * b;
String format = String.format("%d times %d = %d", a, b, a * b);
String formatted = "%d times %d = %d".formatted(a, b, a * b);
System.out.println(concatenated);
System.out.println(format);
System.out.println(formatted);
}
Java SE 21可以用更直觀的方法實現字串的拼接
public static void stringTest21() {
int a = 1;
int b = 2;
String interpolated = STR. "\{ a } times \{ b } = \{ a * b }" ;
System.out.println(interpolated);
String dateMessage = STR. "Today's date: \{
LocalDate.now().format(
// We could also use DateTimeFormatter.ISO_DATE
DateTimeFormatter.ofPattern("yyyy-MM-dd")
) }" ;
System.out.println(dateMessage);
int httpStatus = 200;
String errorMessage = "error pwd";
String json = STR. """
{
"httpStatus": \{ httpStatus },
"errorMessage": "\{ errorMessage }"
}""" ;
System.out.println(json);
}
Unnamed Patterns and Variables(預覽功能)
作為預覽功能引入,未命名模式匹配一個記錄元件,但不宣告元件的名稱或型別。未命名變數是可以初始化但不使用的變數,都可以使用下劃線字元 (_) 來表示它們。
例如:
try {
int number = Integer.parseInt(string);
} catch (NumberFormatException e) {
System.err.println("Not a number");
}
其中 e 是未使用的變數,可以寫成
try {
int number = Integer.parseInt(string);
} catch (NumberFormatException _) {
System.err.println("Not a number");
}
再如
Object object = null;
if (object instanceof Points(int x, int y)) {
System.out.println("object is a position, x = " + x);
}
其中 y 是未使用的變數,可以寫成
Object object = null;
if (object instanceof Points(int x, int _)) {
System.out.println("object is a position, x = " + x);
}
switch 表示式中也可以有類似的用法,例如
Object obj = null;
switch (obj) {
case Byte b -> System.out.println("Integer number");
case Short s -> System.out.println("Integer number");
case Integer i -> System.out.println("Integer number");
case Long l -> System.out.println("Integer number");
case Float f -> System.out.println("Floating point number");
case Double d -> System.out.println("Floating point number");
default -> System.out.println("Not a number");
}
也可以寫成
Object obj = null;
switch (obj) {
case Byte _ -> System.out.println("Integer number");
case Short _ -> System.out.println("Integer number");
case Integer _ -> System.out.println("Integer number");
case Long _ -> System.out.println("Integer number");
case Float _ -> System.out.println("Floating point number");
case Double _ -> System.out.println("Floating point number");
default -> System.out.println("Not a number");
}
Unnamed Classes and Instance Main Methods (預覽功能)
預覽功能,簡言之,就是main方法可以更加精簡,原先寫一個 Hello World 需要這樣做
public class UnnamedClassesAndInstanceMainMethodsTest {
public static void main(String[] args) {
System.out.println("hello world");
}
}
現在可以簡化成
public class UnnamedClassesAndInstanceMainMethodsTest {
void main() {
System.out.println("hello world");
}
}
注:上述程式碼需要在命令列執行,目前IDE還不支援,在命令列下執行:
java --enable-preview --source 21 UnnamedClassesAndInstanceMainMethodsTest.java
輸出:hello world