【问题标题】:Check method parameter for null or not?检查方法参数是否为空?
【发布时间】:2014-07-04 14:12:53
【问题描述】:

我有一个不允许 null 作为参数的方法。我是否应该检查方法内的参数是否为 null 并抛出 IllegalArgumentException? 如果是,我将不得不在很多方法中实现该检查,它看起来很难看。 那么最好的方法是什么?

【问题讨论】:

  • 据我所知,我认为没有办法解决这个问题。您应该在调用方法时或在方法本身内部进行检查。
  • Project Lombok 在构造函数上为此目的有一个 @NotNull 注释。在方法上,您可以使用 Guava 的 Preconditions.checkNotNull 之类的东西。这很容易被模仿。

标签: java design-patterns methods null


【解决方案1】:

嗯,这是个人喜好的问题。我会说:是的,你应该。如果在您第一次访问对象时抛出异常而不是在第一次访问对象时抛出异常,那么调试起来会容易得多,也许在数千行之外的其他方法中。 (但抛出 NullPointerException 而不是 IllegalArgumentException。)

但您必须手动执行此检查。当然,你可以写一个辅助方法或者使用 Guava 的Preconditions

public void test(final String string) {
    Preconditions.checkNotNull(string); // will throw a NullPointerException if string is null
}

编辑:特别是如果您编写一个供他人使用的 API,告诉人们您是否期望非 null 值或 null 是否可以是很有帮助的。您可以使用位于javax.annotation(不是JDK 的一部分)中的@Nullable@Nonnull(每个变量或字段)、@ParametersAreNonnullByDefault@ParametersAreNullableByDefault 注释(每个类、包或方法)来执行此操作.

编辑 2:好的,为什么我建议使用 NPE 而不是 IAE?首先,这是处理这个问题的标准方法。 JDK 做到了这一点,像 Guava 这样的重要库也做到了这一点,而且唯一一本关于 Java 的书,Effective Java,推荐它(第 60 条)。但我知道,这不是一个有效的论点。在@fabian 提到的this answer 中,@Jason Cohen 支持 IAE。他的论点是:

  • 例外情况的文档/定义。 是的,有一个适用案例列表。但是 JavaDoc 也指出它不是整体的。事实上,它声明“应用程序应该抛出此类的实例以指示空对象的其他非法用途。”这正是我们在这里所做的。
  • 对堆栈跟踪阅读器的期望。 首先,我怀疑他的假设是否正确。如果我看到 IAE,我会想到一个非法的。如果我看到 NPE,问题就很明显了:null。其次,我认为这些期望在这里不是一个有效的论据。如果每个人都在 null 参数上抛出 NPE,那么这些期望就会改变。许多人误解了一种行为这一事实并不意味着这种行为是错误的。
  • IAE 更合适。 这是个人问题。如上所述,我认为 NPE 更合适,因为它表示 null 值。既然 NPE 显然是为处理 null 值而设计的,那么您为什么要选择 IAE 呢? ;)
  • null 和非法值之间没有区别。区别。老实说:我不喜欢这样。我真的很欣赏 Ceylon 将 null 作为 Null 类的唯一实例的方法。 (在我的 Java 代码中,我通常使用 Guava 的 Optional 类来表示可空变量。)但是 Java 作者做出了明确的决定:null 是一个非常特殊的东西,不同于所有其他值。这就是为什么应该以不同方式处理它的原因——例如。 G。有一个不同的例外。 IAE 表明某个值有问题:可能太短、太长、负数、正数、零。 NPE 表示根本没有价值。

我更喜欢 NPE 的另一个原因是一致的行为。从调用者的角度来看——假设我不知道方法实现——我必须假设调用带有null 参数的方法会在访问该参数时导致 NPE。在手动检查中抛出 NPE 不会改变这种行为。它只是提高了引发异常的那一刻。

此外,使用 NPE 可以让我以非常简单的方法省略手动检查,例如。 g.:

public void test(@Nonnull final String string) {
    string.toString();
}

【讨论】:

  • 请告诉我们更多关于您选择的异常类型的信息。如果您查看this answer,似乎应该首选IllegalArgumentException(顺便说一句,这将是我的选择)
  • @fabian 我不知道有人喜欢IllegalArgumentException。实际上,我阅读了推荐 NPE(第 60 条)的Effective Java,并且我看到许多主要的库(如 Guava)也使用 NPE。阅读您提到的答案后,我仍然赞成 NPE,但评论字段太短,无法解释。 ;) 我会在我的回答中添加一些关于这个主题的词。
  • @fabian 好吧,我写了一点。
【解决方案2】:

我参加聚会有点晚了,但 Java 1.7 添加了Objects#requireNonNull

这只是一个简单的方法,如果参数为空,它将抛出NullPointerException。我个人喜欢这比在逻辑本身内部失败要好得多,因为该方法不仅快速失败,而且不需要在多变量语句中猜测哪些变量为空。

该方法返回对 Setter 和 Constructors 有帮助的非空值:

public Repot(Date reportDate, String message) {
    this.reportDate = Objects.requireNonNul(reportDate);
    this.message = Objects.requireNonNul(message);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    相关资源
    最近更新 更多