1. 概述
从 Spring 5 开始,我们迎来了一个非常实用的功能 —— null 安全(null safety)。它由一组注解组成,就像代码的“安全卫士”,帮我们提前发现潜在的 null 引用问题。
⚠️ 与放任不安全代码不同的是,null 安全机制会在编译期就给出警告,从而避免运行时出现灾难性的空指针异常(NPE)。
2. @NonNull
注解
在所有 null 安全相关的注解中,@NonNull
是最核心的一个。✅ 它可以用于任何对象引用的地方,包括字段、方法参数或返回值,用来声明该引用不允许为 null。
举个例子,假设我们有一个 Person
类:
public class Person {
private String fullName;
void setFullName(String fullName) {
if (fullName != null && fullName.isEmpty()) {
fullName = null;
}
this.fullName = fullName;
}
// getter
}
这段代码虽然合法,但存在隐患:fullName
字段可能被设置为 null。一旦发生这种情况,在后续使用 fullName
时可能会抛出 NPE。
这时候,如果你用 IntelliJ IDEA 并给 fullName
字段加上 @NonNull
注解,IDE 就会提示你一个警告:
通过这个提示,我们可以提前发现问题并做出调整,避免运行时出错。
3. @NonNullFields
注解
虽然 @NonNull
很有用,但如果每个字段都手动加上这个注解,代码会变得冗余不堪。❌
为了解决这个问题,Spring 提供了另一个利器:@NonNullFields
。✅ 这个注解作用于包级别,表示当前包下所有的字段默认都不能为 null。
要启用这个注解,我们需要在对应包的根目录下创建一个名为 package-info.java
的文件,并添加如下内容:
@NonNullFields
package org.baeldung.nullibility;
接着我们在 Person
类中新增一个属性 nickName
:
package org.baeldung.nullibility;
// import statements
public class Person {
private String nickName;
void setNickName(@Nullable String nickName) {
if (nickName != null && nickName.isEmpty()) {
nickName = null;
}
this.nickName = nickName;
}
// other declarations
}
此时即使没有给 nickName
加上 @NonNull
,IDE 依然会提示类似的警告信息:
✅ 使用 @NonNullFields
能让我们的代码更简洁,同时保持和 @NonNull
一样的安全性。
4. @Nullable
注解
既然有了默认非空的设定(如 @NonNullFields
),那如果某些字段确实允许为 null 怎么办?这时候就需要用到 @Nullable
注解。
回到上面的例子,我们给 nickName
字段加上 @Nullable
注解:
@Nullable
private String nickName;
你会发现之前的警告消失了:
✅ 所以说,**@Nullable
可以覆盖包级的 null 安全策略,灵活地指定某个字段可以为 null。**
5. @NonNullApi
注解
前面提到的 @NonNullFields
只对字段生效。如果我们还想对方法的参数和返回值也做同样的限制呢?
这时候就要请出 @NonNullApi
注解了。✅ 它和 @NonNullFields
类似,也需要在 package-info.java
中声明:
@NonNullApi
package org.baeldung.nullibility;
然后我们给 nickName
添加一个 getter 方法:
package org.baeldung.nullibility;
// import statements
public class Person {
@Nullable
private String nickName;
String getNickName() {
return nickName;
}
// other declarations
}
由于启用了 @NonNullApi
,IDE 会提示 getNickName()
方法可能返回 null:
✅ 同样地,你也可以在方法上使用 @Nullable
来覆盖包级别的 null 约束。
6. 总结
Spring 的 null 安全机制是一套非常实用的工具,能显著降低 NPE 发生的概率。不过有两点需要注意:
❌ 它只在支持的开发工具中有效(比如 IntelliJ IDEA)
❌ 它不会在运行期强制检查 null —— 也就是说,最终防止 NPE 还得靠你自己写好代码
本教程的完整源码可以在 GitHub 上找到。