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

相关推荐
你这个代码我看不懂17 小时前
磁盘的存储原理
java
PyAIGCMaster17 小时前
开发了一个全自动接入wordpress的saas发文章的网站,记录一下如何实现,有需要的朋友联系。
java·开发语言·数据库
研究点啥好呢17 小时前
3月21日GitHub热门项目推荐|攻守兼备,方得圆满
java·c++·python·开源·github
椰猫子17 小时前
JDK概述、Maven概述、IDEA概述、常见注解、 Spring Boot + SSM概述、RESTFul编程风格概述
java·ide·intellij-idea
bearpping17 小时前
Java进阶(ElasticSearch的安装与使用)
java·elasticsearch·jenkins
你这个代码我看不懂17 小时前
引用计数法存在的问题
java·jvm·算法
NWU_白杨17 小时前
Object类与阻塞队列
java
大福猫17 小时前
#一个33岁新手小白在黑马学习程序员的第四天-1
java
Java基基17 小时前
Idea 插件推荐可直接修改jar包内文件的IDEA插件,无需解压
java·ide·intellij-idea
刘大猫.17 小时前
java工具:《返回字符串非零的最后一个层级》
java·字符串·java字符串·返回非零层级·解析字符串