【问题标题】:Choosing between NullPointerException and IllegalArgumentException for signalling error at object construction在 NullPointerException 和 IllegalArgumentException 之间进行选择以在对象构造时发出错误信号
【发布时间】:2012-06-22 16:44:33
【问题描述】:

我有一个关于 Java 最佳实践的问题。我正在写一个类,它非常依赖于构造中的对象。事实上,如果在构造时传入的对象为空,那么大部分功能都没有意义。我认为最好在对象构造时将 null 作为参数传递的情况下抛出异常,但我不知道在这种情况下最合适的异常是什么。我应该抛出 NullPointer、IllegalArgument、Instatiation 还是初始化异常?

我已经看到这些都在整个 Java 源代码库中使用,我似乎无法区分为什么在某些情况下使用 NullPointer 而在其他情况下使用 IllegalArgument。我个人会认为,如果在构造时传入了错误的参数,应该会出现一些初始化错误。

【问题讨论】:

  • 如果你对对象做任何事情,Java 会抛出 NPE 本身。
  • 非常真实的Mong,但我想立即告诉客户。这将在运行时隐藏之前捕获任何错误。

标签: java exception nullpointerexception


【解决方案1】:

首先,您应该绝对抛出异常。这是正确的做法。

至于你应该抛出IllegalArgumentException 还是NullPointerException - Josh Bloch 在 Effective Java 中谈到了这一点,并且普遍认为 NullPointerException 是一个合理的选择。我不完全确定我是否同意(我可能会选择IllegalArgumentException),但最终它不太重要:你不应该直接捕捉这些异常,堆栈跟踪会告诉你哪里有问题.

(遗憾的是,Java 没有与 .NET 的 ArgumentNullException 等效的功能,这意味着它听起来确实如此。)

我个人是 Guava 的 Preconditions 类的忠实粉丝:

public class Foo {
  private final Bar bar;

  public Foo(Bar bar) {
    this.bar = Preconditions.checkNotNull(bar);
  }
}

(有时与checkNotNull 的静态导入一起使用。)

【讨论】:

  • +1:没有什么能阻止你创建自己的ArgumentNullException。无论如何,客户不应该抓住它......
【解决方案2】:

IllegalArgument 向使用该代码的开发人员清楚地说明了问题所在以及我想说的解决方法。它还清楚地表明,如果没有该对象,该方法将无法工作。

NullPointer 意味着他们必须考虑一下问题是什么(不多),并且可能意味着代码更干净,但就像我上面所说的那样。从文档的角度来看,尚不清楚您的代码是否可以使用空值。

【讨论】:

  • 恭喜迪斯科,你的答案被 Jon Skeet 选中。
  • 我更愿意将 NullPointerExceptions 留给 VM,并且从不明确抛出它们。因此参数检查会抛出 IllegalArgumentException。
  • 是的,我希望我没有因为不接受 Jon Skeet 的回答而冒犯了他,但我认为 Disco 可以更多地使用代表点数。
【解决方案3】:

如果您认为平台异常没有为客户提供足够的信息来理解和解决问题,您可以创建自己的在这方面更合适的异常,例如 .NET 的 ArgumentNullException;这将告诉客户问题是什么以及如何解决问题

【讨论】:

    【解决方案4】:

    NullPointerException 用于当您期望一个有效对象但得到null 时。这在尝试调用 null 对象上的方法时尤其重要。这是它最常见的用途。但是,您的情况也可能有必要。

    IllegalArgumentException 用于当您收到的参数不是您期望的或错误类型/样式/等的方法时。 在我看来,这在你的情况下会更合适。您期望一个有效的对象,但您收到了 null 作为参数。此参数值无效 - 所以我会抛出 IllegalArgumentException 并在异常消息中指定问题所在,例如:

    public MyClass(InputObject obj) {
        if(obj == null) {
            throw new IllegalArgumentException("null passed to MyClass constructor");
        }
    
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-03
      • 2010-12-20
      • 2011-09-07
      • 1970-01-01
      相关资源
      最近更新 更多