Java SE 20 新增特性

2023-05-03 21:00:23

Java SE 20 新增特性

作者:Grey

原文地址:

部落格園:Java SE 20 新增特性

CSDN:Java SE 20 新增特性

原始碼

源倉庫: Github:java_new_features

映象倉庫: GitCode:java_new_features

Switch型別匹配(第四次預覽)

Java SE 17 新增特性中,Switch 型別匹配作為預覽功能推出,到 Java SE 20 ,這個功能已經是第四次預覽版,在 Java SE 17 中,可以通過加強 switch 表示式和語句的模式匹配能力,減少了定義這些表示式所需的模板,此外,switch 中增加了空值的支援。如下範例:

注:執行如下程式碼需要基於 Java SE 17 + ,且增加--enable-preview引數。

package git.snippets.jdk20;


/**
 * switch型別匹配(二次預覽)
 *
 * @author <a href="mailto:[email protected]">Grey</a>
 * @date 2023/05/03
 * @since 20
 */
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 -> {
            }
        }
    }
}

範圍值(Scoped Value,孵化階段)

JEP 429 在 Java SE 20 的孵化階段引入了範圍值(ScopedValue), 範圍值可以與虛擬執行緒很好地結合。它允許在有限的時間記憶體儲一個值,而且只有寫入該值的執行緒可以讀取它。類似ThreadLocal對於執行緒的作用。詳見:SCOPED VALUES IN JAVA

record 的匹配增強(第二次預覽)

record 的匹配增強首次預覽在 Java SE 19, record 可以與 instanceof 一起使用,也可以使用 switch 來存取記錄的欄位,而無需強制轉換和呼叫存取器方法,一個 record 的範例如下

package git.snippets.jdk20;

/**
 * record 模式匹配增強(二次預覽)
 * 需要增加 --enable-preview引數
 *
 * @author <a href="mailto:[email protected]">Grey</a>
 * @date 2022/9/22
 * @since 19
 */
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) {
}

此外,在 JEP 432 中,Java SE 20 的 record 支援型別推斷,例如,定義瞭如下資料結構

interface Multi<T> {}

record Tuple<T>(T t1, T t2) implements Multi<T> {}

record Triple<T>(T t1, T t2, T t3) implements Multi<T> {}

在 Java SE 20 之前,需要這樣做

    // 需要指定型別
    static void preJDK20(Multi<String> multi) {
        if (multi instanceof Tuple<String>(var s1, var s2)) {
            System.out.println("Tuple: " + s1 + ", " + s2);
        } else if (multi instanceof Triple<String>(var s1, var s2, var s3)) {
            System.out.println("Triple: " + s1 + ", " + s2 + ", " + s3);
        }
    }

需要指定型別,例如:本範例需要指定 String 型別。

到了 Java SE 20,record 有型別推斷,所以上述程式碼可以寫成

    static void JDK20(Multi<String> multi) {
        if (multi instanceof Tuple(var s1, var s2)) {
            System.out.println("Tuple: " + s1 + ", " + s2);
        } else if (multi instanceof Triple(var s1, var s2, var s3)) {
            System.out.println("Triple: " + s1 + ", " + s2 + ", " + s3);
        }
    }

在迴圈中也可以支援類似的用法,範例如下:

在 Java SE 20 之前

record Position(int x, int y) {
}
static void preJDK20Loop(List<Position> positions) {
    for (Position p : positions) {
        System.out.printf("(%d, %d)%n", p.x(), p.y());
    }
}

在 Java SE 20 版本中,可直接寫成如下形式

    static void JDK20Loop(List<Position> positions) {
        for (Position(int x, int y) : positions) {
            System.out.printf("(%d, %d)%n", x, y);
        }
    }

此外,在 Java SE 20 中,移除了對 record 命名模式的支援,在 Java SE 19 中,如下寫法是對的

        if (object instanceof Points(int x, int y) points) {
            System.out.println("pre jdk 19 object is a position, x = " + points.x()
                    + ", y = " + points.y());
        }

但是到了 Java SE 20 ,已經將上述寫法廢棄,Java SE 20 只支援如下兩種寫法

     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());
        }

廢棄 java.net.URL 的構造方法

java.net.URL的建構函式已被標記為"廢棄"。應該使用URI.create(..)URI.toURL()方法。下面是一個例子:

package git.snippets.jdk20;

import java.net.URI;
import java.net.URL;

/**
 * URL的構造方法被徹底廢棄
 *
 * @author <a href="mailto:[email protected]">Grey</a>
 * @date 2023/05/03
 * @since 20
 */
public class URLConstructorTest {
    public static void main(String[] args) throws Exception {
        // 以下構造方法在 Java SE 20 被徹底廢棄
        // URL url = new URL("xxx");
        // Java SE 20 用如下方法構造 URL
        URL url = URI.create("xxx").toURL();
    }
}

更多

Java SE 7及以後各版本新增特性,持續更新中...

參考資料

Java Language Changes for Java SE 20

JDK 20 Release Notes

JAVA 20 FEATURES(WITH EXAMPLES)