Java基础、中级、高级、架构面试资料

烂尾了,Spring7官宣移除JSR305,联手JSpecify整顿@NonNull

JAVA herman 28浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云

不知道大家注意没注意到,Spring 7.x、Spring Boot 4.x 也或者说是 Spring Cloud 2025.x,它们都在版本发布说明里提到了@NonNull注解或者是对 JSpecify 的支持。按说@NonNull注解并不新鲜呀,为啥它们又旧事重提了呢?

唉,今天我们就一起来聊聊这其中的故事。一个天下苦 @NonNull 久矣,JSpecify 终结 Java 空指针注解十年之乱的故事。

@NonNull

@NonNull 不是一个“新注解”,而是 Java 生态对空指针异常的终极答案。

我相信很多 Java 开发者都遇到过这样的场景。当你想标记一个参数不允许为 null 时,IDEA 自动补全会友好地提醒你,这里有 5 个@NonNull,你想要哪个?

  • javax.annotation.Nonnull
  • org.springframework.lang.NonNull
  • lombok.NonNull
  • androidx.annotation.NonNull
  • com.alibaba.nacos.shaded.javax.annotation.Nonnull

面对这一堆“NonNull”,有些人可能会犯选择困难症。选 javax?还是 Spring 的?更诡异的是,当你使用Nacos自带的@Nonnull时,IDEA 居然不给你任何警告;但换成Spring@NonNull后,黄色警告立刻出现。这难道是 IDEA 也学会了“看人下菜碟”了吗?

下面的代码,大家可以自行试一试,看看不同的结果。

// 实验1:使用Spring的@NonNull
public void test(@org.springframework.lang.NonNull String a) {}
test(null); // IDEA警告:传递了null给非空参数

// 实验2:使用Nacos的@Nonnull  
public void test(@com.alibaba.nacos.shaded.javax.annotation.Nonnull String a) {}
test(null); // IDEA安静如鸡,毫无反应

// 实验3:使用原生的javax.annotation.Nonnull
public void test(@javax.annotation.Nonnull String a) {}
test(null); // IDEA再次警告

为什么同样的语义,IDEA 要区别对待?为了揭开这个谜团,要从一个“沉睡”了 18 年的标准说起。

JSR305

不知道,大家还记得这个规范不?大家可以找找自己的项目里,是不是有一个 jsr305.jar 包文件。这个 jsr305 我正看反看,它都不像是 Java 的“亲儿子”,更像是被 Java 官方给遗忘了的 Java 规范。

现在的NonNull很混乱,而这一切混乱的根源,都指向一个编号JSR-305https://jcp.org/en/jsr/detail?id=305)。

什么是 JSR305?

JSR305(Java Specification Request 305)是 2006 年启动的一个 Java 规范提案,全称是Annotations for Software Defect Detection软件缺陷检测注解。它期望为 Java 引入一套标准的静态分析注解,用于帮助 FindBugs、IDE 等工具检测潜在的代码缺陷,核心就是@Nonnull@Nullable@CheckForNull等空指针相关的注解。

这些注解在javax.annotation包下,由jsr305.jar提供。

JSR305 的休眠之谜

然而,这个始于 2006 年的规范,在 2025 年的今天,状态仍然是Dormant(休眠)。这意味着:

  1. 无人维护:没有官方团队持续推动演进
  2. 设计缺陷:原始设计对泛型、数组、类型边界等复杂场景支持不足
  3. 生态分裂:各大厂商(Google、Spring、JetBrains、Alibaba 等)各自实现,互不兼容

而且,这个休眠,时间也太长了吧。都快 20 年了,一直没啥动静,从 2006 到目前的状态标记为了Dormant,意思是休眠的JSR305其实没人管。细细算下来,它大于“存活”了约 6 年时间,其它时间都是“休眠”状态。

正是这种“放养”状态,导致 Spring、Nacos、Lombok 等框架不得不重复造轮子,定义自己的 @NonNull 注解,但每个注解的“法律效力”却各不相同。

JSpecify 的救赎

既然 JSR305 醒不过来,那我们就再造一个标准。这是 Google、JetBrains、Uber、Pivotal、Square 等巨头在 2019 年达成的共识,这就是大厂联盟的救赎。

JSpecify 是什么?

JSpecify 是一个全新的、独立于 JSR 的注解库项目,其使命是:为 Java 提供一套精确、统一的空指针注解标准

官网的定义也非常简洁。

JSpecify provides precise, tool-friendly annotations for Java nullness analysis, enabling better static checking and Kotlin interoperability.

翻译过来,大致就是:JSpecify 为 Java 中的 null 情况分析提供了精确且易于使用的注释功能,从而有助于提升静态检查能力并增强 Kotlin 的互操作性

它的核心优势有以下 4 点。

第一、彻底解决问题:支持泛型、数组、变长参数的元素级空指针注解。

// 可以精确到泛型参数
List<@NonNull String> nonNullElements;

// 数组元素的空性
String @NonNull [] nonNullArray;

第二、规范明确。提供详细的语义规范,避免歧义。
第三、大厂背书。由 Google、JetBrains、Microsoft、Uber、Spring 等联合维护。
第四、零依赖。纯注解库,不依赖运行时组件。
第五、完美兼容 Kotlin。解决 JSR305 与 Kotlin 互操作的长期痛点。

里程碑时刻

2024 年,JSpecify 1.0.0 正式版发布。这是 Java 空指针注解混乱史的终结时刻。

从 2019 年的萌芽,到 2024 年,历时近 5 年,JSpecify 终于迎来了它的里程碑时刻。

Spring 7 拥抱 JSpecify

在 Spring Framework 7.0 的 Release Notes 中,官方用了一个专门的章节宣告这一变革。

Spring nullness annotations with JSR 305 semantics are deprecated in favor of JSpecify annotations

带有 JSR 305 语义的 Spring 空值注解已被弃用,取而代之的是 JSpecify 注解。

看起来,Spring 好像早就看不过这个 jsr 305 了。专门用一章,大篇幅的介绍 JSpecify,像是一个“独立宣言”一样。

Spring 7 做了什么?

总结下来,有下面 4 点。

  1. 全量迁移:Spring Framework 代码库已将所有空指针注解迁移到 JSpecify
  2. 功能增强:现在可以精确指定数组/变长参数元素的空性
  3. Kotlin 友好:修复了 JSR305 在 Kotlin 中导致的 nullability 不一致问题
  4. 平滑过渡:原有spring-core中的@NonNull@Nullable被标记为@Deprecated,但保留兼容

同样是为了兼容性,看看我昨天那篇文章,Java 的“甩链子”,和 Spring 的决绝果断,一个像在天上,一个像在地上。

而且 Spring 官方给出的理由非常直接。

  • JSR305 处于 Dormant 状态,缺乏维护
  • JSpecify 提供了更精确的规范
  • 更好的工具链支持(IDEA、ErrorProne、NullAway 等)
  • 彻底解决与 Kotlin 的互操作问题

使用或迁移示例

旧代码,Spring 6.x 等版本中的用法如下。

import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

public class UserService {
    public User getUser(@NonNull String id) {
        return userRepository.findById(id);
    }
}

新版 Spring 7.x 中的相关注解用法如下代码所示。

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;

public class UserService {
    public User getUser(@NonNull String id) {
        return userRepository.findById(id);
    }
}

很明显,包名从org.springframework.lang变为org.jspecify.annotations,但 IDE 和编译器的检查精度将大幅提升。

IDEA 区别对待的真相

回到开头的实验,现在我们可以完整解释 IDEA 的行为。

// Nacos的@Nonnull实现
@Retention(RetentionPolicy.CLASS)
public @interface Nonnull {}  // 光秃秃的注解,无任何元信息

// JSR305的@Nonnull实现  
@Retention(RetentionPolicy.RUNTIME)
public @interface Nonnull {} // 同样光秃秃

// Spring的@NonNull实现
@org.springframework.lang.NonNull
// 元注解叠加,IDEA 识别到了 JSR305 版本
@javax.annotation.Nonnull  
public @interface NonNull {}

最核心的原因如下所示。

  1. IDEA 内置了对javax.annotation.Nonnull的硬编码识别
  2. Spring 为了兼容 JSR305,在自己的注解上加了元注解@javax.annotation.Nonnull
  3. Nacos 的注解没有添加任何元信息,IDEA 不认识它,所以不会触发检查

这种“区别对待”恰恰暴露了 JSR305 生态的致命问题,没有工具层面的统一标准

JCP 无作为

历史的车轮滚滚向前,从混乱到统一,从 JSR305 到 JSpecify,说白了就是 JCP 的“无作为”。

下面是它们的时间线回顾。

  • 2006 年:JSR305 启动,提出空指针注解草案
  • 2012 年:JSR305 进入 Dormant 状态,生态开始分裂
  • 2019 年:JSpecify 项目启动,大厂联手
  • 2024 年:JSpecify 1.0.0 发布
  • 2025 年:Spring 7.0 正式采用 JSpecify,宣告 JSR305 时代终结

表明看像是技术演进的胜利,实际上更值得称赞的是社区协作的典范。当 JCP(Java Community Process)无法推动一个休眠的 JSR 时,Google、JetBrains、Pivotal 等企业选择绕开官僚流程,用代码说话,最终创造了一个更好的标准。

结语

“天下共主 Java”,天下又苦 @NonNull 久矣,如今终见曙光。

JSpecify 不是简单的“又一个注解库”,而是 Java 生态对过去 18 年空指针注解混乱的彻底反思与重构。Spring 7 的拥抱,标志着主流框架的共识已经形成。

对于我们大多数 Java 开发者而言,这意味着。

  • 更少的困惑:再也不用纠结用哪个 @NonNull
  • 更强的检查:工具链能精准发现 null 安全问题
  • 更好的互操作:Java 与 Kotlin 的无缝协作
  • 更统一的标准:大厂联合维护,长期稳定

历史会遗忘 JSR305,同样也会让我们记住这个包名org.jspecify.annotations,它比将是未来十年 Java 空指针安全的代名词。

参考资料

  • https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-7.0-Release-Notes
  • JSpecify 官方文档: https://jspecify.dev/docs/user-guide/
  • https://jcp.org/en/jsr/detail?id=305

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » 烂尾了,Spring7官宣移除JSR305,联手JSpecify整顿@NonNull