我正在探索在重构我正在研究的代码库的一部分时消除null的可能性。我们已升级到java 8,因此我们可以使用Optional<T>
。为了有效地执行此操作,我们需要确保不将null传递给任何方法(这是在我们从Optional
中包装从外部服务/库进入我们系统的任何潜在空值之后)。处理此问题的显而易见的方法是显式检查null并在必要时抛出IllegalArgumentException
,但是,这将是不合理的冗长和手动。是否有更少的手动/更简洁的方式来做到这一点?
答案 0 :(得分:9)
您可以使用Objects::requireNonNull
来完成此操作。例如,在构造函数中,您可以执行以下操作:
this.myField = Objects.requireNonNull(myField);
如果您通过NullPointerException
,则会抛出null
。
避免过度使用Optional
。请参阅示例this answer。
答案 1 :(得分:4)
您可以尝试使用@NonNull注释的Lombok注释处理器。使用NonNull注释参数将在编译期间自动生成空值检查,因此您将在运行时获得NullPointerException
或IllegalArgumentException
(无论您喜欢哪个)。
答案 2 :(得分:3)
我将使用以下方法,该方法将@Nonnull
注释(静态分析)与通过Guava's Preconditions的显式,失败快速运行时检查相结合:
import javax.annotation.Nonnull;
import static com.google.common.base.Preconditions.checkNotNull;
public void doSomething(@Nonnull MyClass input) {
checkNotNull(input);
/* Do something */
}
@Nonnull
注释使兼容的IDE或静态分析工具(如FindBugs)能够标记明显违反合同的客户端代码。作为额外的防御层,checkNotNull
保证如果由于某种原因传入了NullPointerException
输入,则该方法会在null
之前及早退出。
答案 3 :(得分:1)
将会有其他答案提出消除检查代码的方法。这些方式往往像魔法一样工作,我并不特别喜欢魔法。因此,我会向您提出一种不完全消除详细程度和手动输入的方法,但将其减少到一半。
java中的断言如下所示:
assert n != null;
如您所见,它占用一行而不是两行,如果您对它引发的throw
异常感到满意,则不需要手动编写AssertionError
语句。通常,我们不会捕获指示错误的异常,所以在大多数情况下你应该没问题,但如果必须确实有IllegalArgumentException
,那么你可以编写你的断言语句如下:
assert n != null : new IllegalArgumentException( "n cannot be null" );
如果n
为null
,则会发生新的AssertionError
异常,并且&#34;导致&#34;这个例外将是你的IllegalArgumentException
。因此,IllegalArgumentException
将出现在堆栈跟踪中,尽管在&#34;引起之后:&#34;线。
作为一个额外的好处,一旦你有一个通过所有测试并且你知道它有效的系统,你就可以避免提供-enableassertions
(简称-ea
)VM选项,以及你的程序将运行得稍快,因为不会评估断言。
答案 4 :(得分:0)
Checker框架提供了一个注释@NonNull
,允许编译时检查是否存在可以将空值传递给带注释的引用的代码路径。
请参阅:https://checkerframework.org/api/org/checkerframework/checker/nullness/qual/NonNull.html