尘世间的上帝之国

View Original

@NotNull 与 @NonNull 辨析

提到Java没有人不想到大名鼎鼎的NPE(Null Pointer Error),可见广大程序员受其毒害之深。所以做接口设计的时候,一个好的习惯就是注明Nullbility。 对于Nullable的参数或者返回值,从Java 8后Optional 是推荐的方式,因为它强迫接口使用者显示进行空值检测。 但如果接口设计中是想注明非空的情况呢,通常情况下你会发现有两个看起来很类似的annotation, @NotNull 以及 @Nonnull, 而且你可能会发现代码库里使用两者的都有。但是,正如Stackoverflow上的这个帖子分析道:

// 用于Java Bean运行时校验,并不用于静态分析
javax.validation.constraints.NotNull

// 被Findbugs用于代码静态分析,已被Deprecate来推荐JSR-305
edu.umd.cs.findbugs.annotations.NonNull

// JSR-305标准,被Findbugs支持并推荐
javax.annotation.Nonnull

// 被Intelliji用来做静态分析
org.jetbrains.annotations.NotNull

准确地说,你应该在接口设计时使用@Nonnull,而且为了达到预计效果,你必须要使用支持JSR-305标准的静态分析工具,比如Findbugs,IDEA或者Checker Framework,不然其效果就是个注释作用,并没有实际检查约束效果。如果你使用了Findbugs而且设置了所有Findbugs错误都会让你的build fail,这样你才充分利用了这个annotation。

那么NotNull该什么使用呢?这个annotation是用在运行时数值验证的,比如:

See this content in the original post

你注明了email不能为空,当你从数据库中加载数据到这个model后你就可以调用validator来检验创建的对象是否遵守规范,或者Person这个对象是Spring web resource的一个请求参数,比如:

public Response register(@Valid Person person) {...}

如果你的web应用开启了bean validation的话person参数就会被自动校验,如果email为null的话resource就会自动返回400 BAD_REQUEST响应,因为客户端发送了一个不合格的数据。

所以看似相似确大不相同,需谨慎使用。