Java SE 25新增特性

Java SE 25新增特性

作者:Grey

原文地址:

博客园:Java SE 25 新增特性

CSDN:Java SE 25 新增特性

源码

源仓库: Github:java_new_features

Patterns、instanceof 和 switch 可以匹配更多类型(第三次预览)

你可以在一个模式(pattern)之后,通过 when 子句紧跟一个布尔表达式。这种用法被称为"带守卫的模式"(Guarded Pattern)。when 子句中的布尔表达式本身,就叫做"守卫"(Guard)。一个值,只有在同时满足两个条件时,才能成功匹配一个"带守卫的模式":

  • 第一,这个值要符合模式本身的要求;
  • 第二,紧随其后的"守卫"表达式必须计算结果为真。

该特性在 Java SE 23 中首次作为预览功能推出,在 Java SE 24 中再度预览。在当前这个版本中,它将再一次以预览的形式发布,并且没有进行任何重大修改。

示例代码如下:

java 复制代码
package git.snippets.jdk25;
/**
 * When Clause
 * @since 25
 */

public class WhenClausesTest {
    void main() {
        test("h");
        doubleToRating(100d);
        bigNumbers(100000000000l);
        testSwitch(new R(33));
    }
    static void test(Object obj) {
        switch (obj) {
            case String s when s.length() == 1 -> System.out.println("Short: " + s);
            case String s                      -> System.out.println(s);
            default                            -> System.out.println("Not a string");
        }
    }
    String doubleToRating(double rating) {
        return switch(rating) {
            case 0d -> "0 stars";
            case double d when d > 0d && d < 2.5d
                    -> d + " is not good";
            case double d when d >= 2.5f && d < 5d
                    -> d + " is better";
            case 5d -> "5 stars";
            default -> "Invalid rating";
        };
    }

    void bigNumbers(long v) {
        switch (v) {
            case long x when x < 1_000_000L ->
                    System.out.println("Less than a million");
            case long x when x < 1_000_000_000L ->
                    System.out.println("Less than a billion");
            case long x when x < 1_000_000_000_000L ->
                    System.out.println("Less than a trillion");
            case long x when x < 1_000_000_000_000_000L ->
                    System.out.println("Less than a quadrillion");
            default -> System.out.println("At least a quadrillion");
        }
    }
    record R(int x) { }
    // ...
    static void testSwitch(R r) {
        switch(r) {
            case R(int x) when x >= 5 -> System.out.println(x + " => 5");
            default -> System.out.println(r.x + " < 5");
        }
    }
}

模块导入声明(第三次预览)

你可以通过一条声明,就导入一个模块(module)所导出的所有包(package)。参考JEP 511

思考下面这个例子,它导入了四个类:

java 复制代码
// 代码部分保留原文
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

// ...

在这个例子中,你可以用"按需类型导入声明"(type-import-on-demand declarations,也就是我们常说的通配符 * 导入)来替换那四条"单类型导入声明"。但即便如此,你仍然需要三条声明:

java 复制代码
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

然而,由于 java.base 这个模块本身就导出了 java.utiljava.util.functionjava.util.stream 这几个包,所以,你现在可以把上面那三条声明,用一条模块导入声明来代替:

java 复制代码
import module java.base;

一条模块导入声明遵循以下格式:

java 复制代码
import module M;

它会按需导入以下所有公共的顶级类和接口:

  • 模块 M 直接导出给当前模块的那些包。

  • 因读取模块 M,而导致当前模块需要间接读取的其他模块所导出的包。这个机制使得一个程序可以直接使用某个模块的 API,而无需手动导入该 API 可能引用到的、来自其他模块的所有类和接口。

举个例子,import module java.sql; 这条声明,其效果等同于 import java.sql.*;并且还加上了java.sql 模块间接导出包的按需导入,这些间接导出的包就包括了 java.loggingjava.xml

示例代码:

java 复制代码
package git.snippets.jdk25;

import module java.base;
import module java.sql;

public class ModuleImportDeclarationsTest {
    void main() throws ParserConfigurationException, SAXException {
        System.out.println(groupByFirstLetter("a", "abc", "bcd", "ddd", "dddc", "dfc", "bc"));
// 我们不需要显式导入 SAXParserFactory 和 SAXParser,也不需要显式导入 java.xml 模块:
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser saxParser = factory.newSAXParser();
    }

    public static Map<Character, List<String>> groupByFirstLetter(String... values) {
        return Stream.of(values).collect(Collectors.groupingBy(s -> Character.toUpperCase(s.charAt(0))));
    }
}

Compact Source Files and Instance Main Methods

这项功能最初在 Java SE 21 中第一次预览版,并在 Java SE 22、23 和 24 中持续预览。在当前版本中,它已成为一项正式功能,其标题也经过了修订。

该版本的具体更新如下:

  • 用于处理基本控制台输入/输出的新类 IO,其位置已从 java.io 包移动到了 java.lang 包。这意味着java.lang 包里的所有东西都会被虚拟机自动导入,所以现在每个源文件都会默认包含 IO 类,你无需再手动去 import 它了。这让代码更加干净。

  • IO 类中的静态方法(比如 println),将不再被默认导入到那些简化的源文件中。这和预览版的行为不同了。因此,现在调用这些方法时必须明确地写出类名,例如 IO.println("Hello, world!"),而不能再像之前那样直接调用 println。当然,如果你觉得每次都写 IO. 很麻烦,也可以通过显式的静态导入(static import)来恢复之前的便捷性。

  • IO 类的底层实现也变了。它现在是基于我们非常熟悉的 System.outSystem.in,而不再是 java.io.Console 类。这是一个内部实现细节的改变,但它意味着 IO 类的行为会和标准的系统输入输出流更加一致。

    示例代码如下:

java 复制代码
/**
 * @author <a href="mailto:410486047@qq.com">Grey</a>
 * @date 2025/09/17
 * @since 25
 */
void main() {
    IO.println("hello world");
}

更多

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

参考资料

Java Language Changes for Java SE 24

JDK 24 Release Notes

JAVA 25 FEATURES(WITH EXAMPLES

相关推荐
mmsx5 分钟前
基于 Android 的校园信息管理系统源码
android·java·okhttp
Buke..24 分钟前
【APP 逆向】哔哩哔哩 sign 参数逆向(上):Frida 反调试绕过与 unidbg 调用
java·开发语言·爬虫·python·安卓
竹枝溪25 分钟前
Tomcat与Servlet全套小白教程
java·servlet·tomcat·cookie·filter·session·listener
UseLessQQ1 小时前
云计算k8s集群部署
java·kubernetes·云计算
我命由我123451 小时前
人脸识别 - 人脸识别选帧
java·人工智能·python·算法·安全·java-ee·人脸识别
宠友信息1 小时前
IM系统开发技术路线分析,即时通讯源码助力快速搭建聊天应用
java·spring boot·redis·websocket·mysql·uni-app·vue
long3162 小时前
封装(Encapsulation)
java·人工智能·ai·ai编程
yaoxin5211232 小时前
502. Java 反射 - 编写 MessageInterceptor 类
java·开发语言
风流 少年2 小时前
Spring AI 2.0:阿里云百炼平台(工作流应用)
java·后端·spring
长谷深风1112 小时前
AI Tool 设计:粒度、参数与错误恢复怎么做
java·大数据·人工智能·ai agent·agent工作流·智能体设计·ai产品设计