想必你应该在代码中经常看到这些注解:@NonNull、@Nullable,这些注解理解起来很容易,比如@NonNull表示某个参数不能为空,@Nullable表示可以为空,但是你是否遇到过这种情况:
当你想用@NonNull时,发现有一堆的@NonNull等着被你用,比如上图中就有spring提供的,有nacos提供的,有javax提供的,各个都是大佬,到底该用哪个呢?
我们先做个测试,当我们用spring提供的@NonNull时,IDEA会给黄色警告:
这是IDEA编译给出的警告,a参数前面加了@org.springframework.lang.NonNull
表示不能为空,但是调用test()方法时又传了空,所以给出警告,但是其实代码是可以运行的。
我们再换成@javax.annotation.Nonnull
注解,发现同样也会给出黄色警告:

我们再换成@com.alibaba.nacos.shaded.javax.annotation.Nonnull
注解,发现不给 黄色警告了:
这就有意思了,都是Nonnull注解,IDEA怎么还区别对待呢?我们来看看上面三个Nonnull注解的定义:
这是Nacos的:
这是javax的:

这是spring提供的:

重点来了,spring提供的NonNull注解上,用到了另外一个NonNull注解,它就是javax中的Nonnull注解。
到这,我们就知道了上面测试中为什么Nacos的Nonnull注解不会给黄色警告,而spring提供的Nonnull会给黄色警告了,本质上是javax中的Nonnull注解在起作用,因为Nacos提供的Nonnull注解之上没有用到javax中的Nonnull注解,而IDEA编译时只会对javax中定义的Nonnull注解进行检查,而不会对Nacos自己定义的Nonnull注解进行检查,因此就出现了上面测试出现的效果。
虽然我们解释了上面测试效果出现的原因,但是你有没有想到,既然javax中提供了NonNull注解,为什么spring、nacos它们还要定义自己的NonNull注解呢?最终导致我们在用的时候出现一堆的NonNull注解?
这里的原因其实是因为javax中的NonNull注解其实处于"放养"状态,我们可以看到javax中的注解来至于jsr305这个jar包:
而JSR305早在2006就开始了,都快20年了,一直没啥动静,目前的状态表标记为了Dormant,意思是休眠的,也就是说JSR305其实没人管的,至于为什么没人管,我还没仔细研究,大概说法是设计的不好,但是我觉得应该还有其他原因,因为就算设计的不好,就几个注解而已,重新设计一下不就行了吗。
因此spring、nacos这些技术可能考虑到JSR305这个样子,都自己定义了一套NonNull等注解,但每个技术都自己定义一套,总归不是好事,大家都在等JSR305醒过来,但是一直没动静,这不,JSpecify来了。

你都不用详细去学JSpecify是什么,它的作用就是顶替JSR305的位置,你半天没动静,我们不能一直等你,所以几个互联网大厂联合起来自己定义了一套NonNull注解,而包名就叫做:

JSpecify 1.0.0正式版是在2024年发布的:
JSpecify 1.0.0刚发布,Spring就开始支持了,会在Spring 7中将spring自己定义的Nullable等注解替换成为jspecify中的:

其他技术和静态编译工具肯定也会陆续支持,到此,关于@NonNull、@Nullable等注解的混乱总算结束了,以后大家都用jspecify提供的就可以了。
好啦,希望这篇文章能帮到大家,如果有帮助,期待你的点赞、关注、分享,感谢!
我的【公众号:IT周瑜】,里面有更多好文章,期待你的关注。