空值安全
尽管 Java 尚未允许通过其类型系统表达空值标记,但 Spring Framework 代码库已使用 JSpecify 注解来声明 API、字段及相关类型用法的可空性。强烈建议阅读《JSpecify 用户指南》以熟悉这些注解及其语义。
该空值安全机制的主要目标是通过构建时检查来防止运行时抛出 NullPointerException,并将显式可空性作为表达值可能缺失的方式。通过利用 NullAway 等空值检查器或支持 JSpecify 注解的 IDE(如 IntelliJ IDEA 和需手动配置的 Eclipse),这在 Java 中非常实用。在 Kotlin 中,JSpecify 注解会自动转换为 Kotlin 的空值安全机制。
运行时可使用 Spring 的 Nullness API 检测类型用法、字段、方法返回类型或参数的可空性。该 API 全面支持 JSpecify 注解、Kotlin 空值安全和 Java 原生类型,并对任何 @Nullable 注解(无论所属包)进行实用检查。
使用 JSpecify 注解标注库
自 Spring Framework 7 起,Spring Framework 代码库采用 JSpecify 注解来提供空安全 API,并通过构建时集成 NullAway 工具校验这些可空性声明的合规性。建议所有依赖 Spring Framework 及 Spring 系列项目(包括 Spring 生态相关库如 Reactor、Micrometer 及 Spring 社区项目)的第三方库均遵循此实践。
在 Spring 应用中运用 JSpecify 注解
使用支持空值注解的 IDE 开发应用程序时,若违反可空性约定,Java 会发出警告而 Kotlin 会报错,这使得 Spring 应用开发者能完善空值处理,避免运行时抛出 NullPointerException。
Spring 应用开发者还可选择为代码库添加注解,并使用 NullAway 等构建插件,在构建时强制执行应用层面的空值安全规范。
指南
本节分享一些关于明确指定 Spring 相关库或应用可空性的建议指南。
JSpecify
默认非空
需要理解的一个关键点是,在 Java 中类型的可空性默认是未知的,且非空类型的使用频率远高于可空类型。为了保持代码库的可读性,我们通常希望默认定义类型使用为非空,除非在特定作用域内标记为可空。这正是 @NullMarked 的目的,该注解通常通过 package-info.java 文件在 Spring 项目中以包级别进行设置,例如:
@NullMarked package org.springframework.core;
import org.jspecify.annotations.NullMarked;
显式可空性
在带有 @NullMarked 注解的代码中,可空类型的使用需通过 @Nullable 显式声明。
JSpecify 的 @Nullable/@NonNull 注解与其他多数变体的关键区别在于:这些注解被元标注为 @Target(ElementType.TYPE_USE),因此仅适用于类型使用场景。这既影响注解的放置位置(需符合相关 Java 规范要求),也涉及代码风格的最佳实践。从代码风格角度,建议将这些类型使用注解直接标注在类型前,并与类型保持同一行。
例如对于字段声明:
private @Nullable String fileEncoding;
或者对于方法参数和方法返回类型:
public @Nullable String buildMessage(@Nullable String message, @Nullable Throwable cause) { // ...
}


