@Nonnull和Objects.requireNonNull有什么区别?

19

以下两个代码片段之间有什么区别?

public Integer getId(@Nonnull SomeObject obj){  
    // do some stuff
    return id;
}

public Integer getId(SomeObject obj){   
    Objects.requireNonNull(SomeObject, "SomeObject is null");
    // do some stuff
    return id;
}

它们之间有哪些重要区别?在这些情况下,正确的空值检查方式是什么?


2
多个方面之一:与Objects.requireNonNull相比,如果未被考虑,该注释不一定会执行任何操作。 - Jan B.
1
@Nonnull 告诉编译器给定的参数不应该为 null,而 requireNonNull 则检查给定的对象是否为 null - MC Emperor
3个回答

22

两者是互补的:@Nonnull注释记录了obj必须非空的事实,而Objects.requireNonNull调用确保obj在运行时是非空的。

你应该像这样结合两者:

public Integer getId(@Nonnull SomeObject obj){   
    Objects.requireNonNull(SomeObject, "SomeObject is null");
    // do some stuff
    return id;
}

@Nonnull的相关文档可以在这里找到:

Optional Type Annotations并不能替代运行时验证

在Type Annotations之前,描述像nullability或ranges等内容的主要位置是在javadoc中。使用Type Annotations后,这种通信以一种编译时验证的方式进入了bytecode。

您的代码仍应执行运行时验证。


2
@Alexander - 你会使用 Kotlin 吗? - Oliver Charlesworth
1
我注意到javax.annotation中的Nonnull接口具有@Retention(RetentionPolicy.RUNTIME)。有人知道这是什么意思吗? - prime
3
如果我错了,请纠正我,那么当我们使用https://projectlombok.org/features/NonNull时,就不需要使用Objects.requireNonNull。 - prime
@prime 您链接的文章是针对他们开发的库和它为您生成的代码的特定内容。 - Sergey Kalinichenko
1
@dasblinkenlight 是的,在那种情况下,我认为该库将负责运行时验证。 - prime
显示剩余3条评论

10

两者的区别在于,第一种情况是编译器和IDE的提示,表明参数不应该为null,因此当您写getId(null)时会出现错误。但是在运行时,有人可能会传递null值。

至于第二种情况,这是一种防御性编程,通过前置条件(参数不应为null)进行快速故障检测。


@prime 是的,在运行时,当将空值作为参数传递并调用该对象的方法时。 - ledniov

7

其中之一是实现JSR-305的注释,但更适合静态分析而非运行时保护。据我回忆,JSR-305在原则上是个好主意,实际上有很多东西以某种方式利用它,但当其效用仅以静态分析的形式出现时,它失去了很多作用。

一个例子是:你的IDE可以利用它来警告您正在传递不应该传递的情况,但它无法防止您在编译时将null传递到此方法中。

Objects.requireNonNull是一个运行时强制执行,无论它传递什么,都将是一个非空引用。编译器也不能强制执行这一点,但在运行时,如果您收到一个null值,那么在执行该代码行时会得到一个NullPointerException

就正确性而言,使用 Objects.requireNonNull 是个好主意,但这取决于你在运行应用程序时的义务是什么。如果你必须在空值上失败,那么使用它是可以的,因为它会生成一个运行时异常来处理。如果你不能在空值上失败,那么使用 if 检查会更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接