Java SE 22 新增特性

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章