【问题标题】:Should an unused argument be null-checked?是否应该对未使用的参数进行空检查?
【发布时间】:2018-06-04 04:43:26
【问题描述】:

给定一个像这样的通用接口(这不是我的实际情况,但作为一个最小的例子)

/** Generic interface for unary functions on strings. */
public interface StringTransformer {
  /**
   * Transform the given non-null string.
   * @param x string to be transformed
   * @return transformed string
   * @throws NullPointerException if x is null
   */
   String apply(String x);
}

假设我有一个实现返回一个常量值,而不管传递的参数如何:

public class EmptyAllStrings implements StringTransformer {
  public String apply(String x) {
    return "";
  }
}

我的疑问是,如果参数是 null,添加检查以抛出 NPE 是否是个好主意,即使在这种情况下无关紧要。

  public String apply(String x) {
    Objects.checkNotNull(x);
    return "";
  }

反对检查的要点:

  • null 可用于已知使用的特定类的情况
  • 更少的代码

支持检查的要点:

  • 有效地兼容接口 javadoc
  • 即使使用了null-resilient 类,也可能有助于发现null 相关的错误

在这种情况下,是否有或多或少的“权威”指南建议两种选择之一?

【问题讨论】:

  • 应删除未使用的参数
  • @Stultuske 如果你想实现一个接口,不要这样做。
  • @daniu 那么该接口应该具有不带参数的方法。这有点像把 setSpeed(int speed);在接口中,在实现中 setSpeed(int speed) { /* 在这里做什么? */ }。当然,它有效,但它是好的设计吗?
  • 我们不是在谈论 setSpeed(int speed),我们在谈论 String apply(String x),您显然无法删除该参数,因为存在一个不是很有用的实现,它没有' t 使用参数。
  • @Stultuske 你在争论Consumer<String> 应该包含一个方法accept()

标签: java nullpointerexception null


【解决方案1】:

我认为问题的根源在于接口的文档中存在@throws NullPointerExceptionNullPointerException 应该用于编程错误,但在这里你只是陈述一个合同,而不是一个实现。让实现类决定如何处理空值,并相应地调整文档。

如果接口代码已给出且不可更改,那么我认为您可以:

  • 检查null,即使您不使用参数(首选)或;
  • 覆盖子类中的文档,声明您的实现不会以任何方式使用该参数,甚至不会用于检查。

【讨论】:

    【解决方案2】:

    我实际上已经看过几次这样做了,我总是有一个问题“为什么?”,基本上这是一个糟糕的开发,正如其他人所说的那样,不是应该抛出 NPE 的代码才是 JVM 启动的地方, NPE 是开发人员错误。拥有一个始终返回相同内容的已实现方法是没有意义的并且不需要因此应该被删除,否则提供正确的实现并进行空检查(如果参数可能为空)抛出带有消息和句柄的 IllegalArgumentEx在其他地方正确。

    【讨论】:

      【解决方案3】:

      我不明白你为什么要在这里检查null。这个想法是由 JVM 抛出 NullPointerException,而不是 Java 代码......如果有的话,我希望为这种检查抛出 IllegalArgumentException(尽管我曾与不同的意见,所以YMMV)。

      不过,在这里,您实际上是从无到有返回一些东西;你不知道周围的代码是否需要null 检查。这不是这段代码的责任。

      Javadoc 注释的意思是“可能抛出异常”,而不是“保证”IMO。

      【讨论】:

      • 我曾经认为 IllegalArgumentException 更合适。但是在NullPointerException documentation 之间,它说“应用程序应该抛出这个类的实例以指示空对象的其他非法使用”,Objects.requireNonNull 抛出它的事实,以及所有 Java API 在传递 null 时抛出它的事实作为一个(不可接受的)论点,我相信这是正确的选择。
      猜你喜欢
      • 2019-02-01
      • 1970-01-01
      • 2015-01-31
      • 2011-04-21
      • 1970-01-01
      • 2013-08-20
      • 1970-01-01
      • 2018-07-19
      • 2018-05-20
      相关资源
      最近更新 更多