【问题标题】:Objects.requireNonNull(T obj) instead of null checks and manually thrown IllegalArgumentException?Objects.requireNonNull(T obj) 而不是空检查并手动抛出 IllegalArgumentException?
【发布时间】:2015-06-23 14:04:17
【问题描述】:

每当我必须检查方法的给定参数是否不为空时,我都会编写一个空检查并在空检查失败时抛出IllegalArgumentException

    if (user == null) {
        throw new IllegalArgumentException("User can't be null.");
    }

但是,通过阅读一些 Java 8 类的源代码,例如 ArrayList,我发现 Oracle 正在使用 Objects.requireNonNull 来检查一个参数是否为空值,然后,如果测试失败,一个 @ 987654324@ 被抛出。

这样,早期的代码sn-p采用这种方式应该是这样的:

Objects.requireNonNull(user, "User can't be null.");

更小,更易读。

假设我可以控制系统的整个异常处理(即使我不应该,有时处理这些未经检查的异常也是业务的一部分),我是否应该将我的IllegalArgumentException 替换为NullPointerException 并使用 Objects.requireNonNull 而不是自己编写 null 检查和异常抛出?

【问题讨论】:

  • 我们在 JDK 中为新代码这样做,并适时调整旧代码。并且很有可能在未来 JVM 最终会内化 Objects.requireNonNull,这也是喜欢它的另一个原因。 “我应该使用 NPE 还是 IAE”的争论主要是一个鼠洞;这两种立场都是站得住脚的,在它们之间争论的大部分努力都白费了。
  • 当 Brian Goetz 说他以一种方式做事时,很可能这就是您想要做的方式 ;-)。
  • @BrianGoetz,这样当这些空检查失败时,我更愿意采用NullPointerException。 Joshua 在他的书中已经说明了对NPE 的偏好,而不是IAE,而且,通过阅读您对 JDK 未来的看法,我认为我有足够的证据可以做到这一点。顺便说一句,@OSryx 的答案仍然有效,可以实现另一种参数检查。
  • @Daniel 我希望这是真的,但是有一个拥有 20 年历史的大型代码库和数百名厨师在厨房里,不一致是不可避免的。但是,有关系吗?这些不是旨在被调用者捕获的异常。更重要的是您要进行任何参数检查。我担心我们花费更多的精力来争论进行论证检查的最佳方式,而不是我们实际花费的时间。
  • 顺便说一句,Objects.requireNonNull() 的 API 允许您在链式 this()super() 调用中使用它:super(requireNonNull(x))

标签: java exception exception-handling java-8


【解决方案1】:

使用Objects.requireNonNull(c) 是检查元素是否不为空的一种非常优雅的方法。但是有一个有趣的讨论是关于选择NullPointerException 还是IllegalArgumentException --> IllegalArgumentException or NullPointerException for a null parameter?。所以抛出NullPointerException 是表达引用为空的java 方式。

否则,您可以制作自己的方法requireNotNull()。很简单:

 public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }

您可以将异常NullPointerException 更改为IllegalArgumentException

【讨论】:

  • 上述讨论中评分最高的答案与此处的答案一起提出了观点。 IllegalArgumentException 看起来更合适,所以我仍然可以使用然后结合我的“自己的版本”Objects.requireNotNull,这会引发我想要的异常。
  • 小心,有时评分最高的答案可能是最老的答案;)
  • 你是对的。通过再搜索一点,我发现即使是 Joshua Bloch 也为使用NullPointerException 而不是IllegalArgumentException 辩护,我打开他的书进行确认。现在我明白为什么它有时被称为“圣战”问题,这两种方法都有优点。但是,这个讨论不是这个话题的想法,所以我可能很快就会接受你的回答。
  • 如果您要自己滚动,您可能需要将 \@Nullable 添加到参数并将 \@NotNull 添加到返回类型。
【解决方案2】:

讨论了当方法接收到它不期望的空值时应该抛出什么样的异常。有人主张NullPointerException,有人主张IllegalArgumentException。 JDK的方式似乎是在这种情况下抛出NullPointerException,这就是Objects.requireNonNull抛出它的原因。

但我不会仅仅因为这种方法而修改现有代码,尽管您可能想考虑在新代码中使用Objects.requireNonNull。 (与检查 null 并手动抛出异常相比,使用它通常会使代码更具可读性。)

【讨论】:

  • 在我工作的地方,我们创建了自己的Ensure.notNull(Object val, String msg),它的作用基本相同。但是,由于 Hoopje 指出的原因,它会抛出 IllegalArgumentException 而不是 NullPointerException。我们发现这更可取,因为它使断言的非空参数明显不同于偶然的 NPX。虽然我还没有在我们的代码库中完成它,但我正在考虑创建一个新的NullArgumentException(扩展IllegalArgumentException)并让它抛出它。
  • 这个“我们发现这更可取,因为它使断言的非空参数明显不同于偶然的 NPX。”有点没有实际意义 - 当你获得 NPE 时,你也有一个行号,因此在这种特定情况下,您可以看到参数为空 - 并且 Objects.requireNonNull 允许您根据需要提供特定的错误消息。
猜你喜欢
  • 1970-01-01
  • 2019-12-11
  • 1970-01-01
  • 1970-01-01
  • 2014-06-15
  • 2015-07-14
  • 2011-09-26
  • 2014-09-18
  • 2014-11-05
相关资源
最近更新 更多