Java SE 22 新增特性

Grey Zeng發表於2024-03-20

Java SE 22 新增特性

作者:Grey

原文地址:

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

CSDN:Java SE 22 新增特性

原始碼

源倉庫: Github:java_new_features

使用未命名的變數和模式

我們經常需要定義一些我們根本不需要的變數。常見的例子包括異常、lambda表示式,例如:

try {
    String string = "xx";
    int number = Integer.parseInt(string);
} catch (NumberFormatException e) {
    System.err.println("Not a number");
}

如果異常變數 e 無須使用,那麼上述例子中的變數 e 可以用 _ 代替

try {
    String string = "xx";
    int number = Integer.parseInt(string);
} catch (NumberFormatException _) {
    System.err.println("Not a number");
}

這個功能在 Java SE 21 中作為預覽功能釋出,詳見Java SE 21 新增特性,在 Java 22 中透過 JEP 456 最終確定,不會有任何更改。

啟動多檔案原始碼程式

自 Java 11 起,我們可以直接執行僅由一個檔案組成的 Java 程式,而無需先對其進行編譯,詳見Java SE 11 新增特性

例如,在 Hello.java 檔案中儲存一次以下 Java 程式碼:

public class Hello {
  public static void main(String[] args) {
    System.out.printf("Hello %s!%n", args[0]);
  }
}

不需要 javac 編譯這個程式,而是可以直接執行它:

java Hello.java

我們也可以在 Hello.java 檔案中定義多個類。但是,隨著程式的增長,這種做法很快就會變得混亂;其他類應該定義在單獨的檔案中,並以合理的包結構組織起來。

然而,一旦我們新增更多的 Java 檔案,Java 11 中所謂的 "啟動單個檔案原始碼 "機制就不再起作用了。

比如定義兩個類:

public class Hello {
  public static void main(String[] args) {
    System.out.println(Greetings.greet(args[0]));
  }
}
public class Greetings {
  public static String greet(String name) {
    return "Hello %s!%n".formatted(name);
  }
}

在 Java SE 11 中,無法執行,因為只支援單個 Java 檔案執行,但是到了 Java SE 22,可以支援多個檔案原始碼執行,比如上述兩個類,在 Java SE 22 下,可以透過

java Hello.java

執行。

Foreign Function 和 Memory API

Project Panama中,取代繁瑣、易出錯、速度慢的 Java 本地介面(JNI)的工作已經進行了很長時間。

在 Java 14 和 Java 16 中已經引入了 "外來記憶體訪問 API "和 "外來連結器 API"--最初都是單獨處於孵化階段。在 Java 17 中,這些 API 被合併為 "Foreign Function & Memory API"(FFM API),直到 Java 18,它一直處於孵化階段。

在 Java 19 中,JDK Enhancement Proposal 424最終將新的 API 提升到了預覽階段,

在 Java SE 22 中,外來函式與記憶體 API 終於由 JDK Enhancement Proposal 454 最終確定。

FFM API 可以直接從 Java 訪問本地記憶體(即 Java 堆外的記憶體)和訪問原生代碼(如 C 庫)。

下面是一個簡單的例子,它在堆外記憶體中儲存一個字串,並對其呼叫 C 語言標準庫的 "strlen "函式。

package git.snippets.jdk22;

import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;


/**
 * FFM API
 * @since 22
 */
public class FFMTest {
    public static void main(String[] args) throws Throwable {
        // 1. Get a lookup object for commonly used libraries
        SymbolLookup stdlib = Linker.nativeLinker().defaultLookup();
        // 2. Get a handle to the "strlen" function in the C standard library
        MethodHandle strlen = Linker.nativeLinker().downcallHandle(stdlib.find("strlen").orElseThrow(), FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));

        // 3. Get a confined memory area (one that we can close explicitly)
        try (Arena offHeap = Arena.ofConfined()) {

            // 4. Convert the Java String to a C string and store it in off-heap memory
            MemorySegment str = offHeap.allocateFrom("Happy Coding!");

            // 5. Invoke the foreign function
            long len = (long) strlen.invoke(str);
            System.out.println("len = " + len);
        }
        // 6. Off-heap memory is deallocated at end of try-with-resources
    }
}

本地化列表

Java SE 22 有了新的 ListFormat 類,我們就可以像在連續文字中一樣,將列表格式化為列舉。

package git.snippets.jdk22;

import static java.text.ListFormat.*;

import java.text.ListFormat;
import java.util.List;
import java.util.Locale;

public class LocaleDependentListPatternsTest {
    void main() {
        List<String> list = List.of("Earth", "Wind", "Fire");
        System.out.println(ListFormat.getInstance(Locale.CHINA, Type.STANDARD, Style.FULL).format(list));
        System.out.println(ListFormat.getInstance(Locale.US, Type.STANDARD, Style.FULL).format(list));
        System.out.println(ListFormat.getInstance(Locale.GERMAN, Type.STANDARD, Style.FULL).format(list));
        System.out.println(ListFormat.getInstance(Locale.FRANCE, Type.STANDARD, Style.FULL).format(list));
    }
}

執行輸出結果

Earth、Wind和Fire
Earth, Wind, and Fire
Earth, Wind und Fire
Earth, Wind et Fire

上述例子表明在不同的 Lacale 設定下,可自動根據配置進行格式化。

更多

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

參考資料

Java Language Changes for Java SE 22

JDK 22 Release Notes

JAVA 22 FEATURES(WITH EXAMPLES

相關文章