【问题标题】:Guava preconditions checkNull, checkArgumentGuava 前置条件 checkNull, checkArgument
【发布时间】:2012-10-09 17:01:40
【问题描述】:

我想检查基类的先决条件,以便我知道子类型将始终使用有效的构造函数参数。

我们以一个构造函数为例:

  1. 需要 2 个或更多参数
  2. 接受不同类型的参数
  3. 对于一个参数,它执行多个检查(例如,字符串不为空并且不为空)

在这种情况下,如何最好地使用 Guava 前置条件方法?

在这样的模拟示例中:(这是人为的!)

protected AbstractException(String errorMessage, Throwable errorCause) {
  super(errorMessage, errorCause);
  checkNotNull(errorMessage,
      ErrorMessage.MethodArgument.CANNOT_BE_NULL_CHECK, "errorMessage");
  checkArgument(!errorMessage.isEmpty(),
      ErrorMessage.MethodArgument.CANNOT_BE_EMPTY_STRING_CHECK,
      "errorMessage");
  checkNotNull(errorCause, ErrorMessage.MethodArgument.CANNOT_BE_NULL_CHECK,
      "errorCause");
}

我最终在检查参数之前调用了super,因为对super 的调用必须是方法的第一行,虽然我可以使用super(checkNoNull(errorMessage)),但我无法使用checkArgument 进行相同的包装因为那会返回void。所以困境是:

  • 在哪里检查所有参数?我不想为此创建一个 Builder
  • 如何像在虚构的checkStringNotNullAndNotEmpty() 中那样“分组”检查
  • 我应该考虑与匹配器框架集成吗? (hamcrest、fest 断言...)

我使用看起来很奇怪的 ErrorMessage.MethodArgument.CANNOT_BE_NULL_CHECK 因为默认的 throw 不包含错误消息,所以从测试方面我无法将其识别为参数验证失败而不是“任何”NPE?

我做错了吗?

【问题讨论】:

  • 不是您问题的答案,但从其他异常的构造函数中抛出异常是个坏主意...
  • 同意。我确实说“做作”。顺便说一句,如果你有一个框架,它只想看到异常被抛出一个错误消息集,你会怎么做?在这个例子中,我重新定义了一个需要消息的上限基数..
  • 我们换个问题:如果Exception 发现不正确的构造函数参数,你会怎么做?您不能抛出验证异常,因为这将丢弃导致您抛出第一个异常的原始问题...
  • 如果框架的用户试图抛出框架异常,AbstractException 的子类,也就是说,与框架抛出的错误消息描述性不足(例如 null、""、...)在尝试创建异常以保护框架前提条件时(即所有异常都可以被记录,因为它们有消息,可以被过滤......过滤的一个例子是我需要一个非空检查来说明它是一:ErrorMessage.MethodArgument.CANNOT_BE_NULL_CHECK)

标签: java guava


【解决方案1】:

这应该是评论,但是太长了。

  • 在测试前调用 super 是无害的,前提是超级 ctor 不做它不应该做的事情
  • 可以通过静态生成器方法防止,您不需要生成器。但这不值得。
  • 我怀疑分组测试通常有用;如果是的话,那么已经有这样的方法了。但是,如果您需要两次以上这样的具体事物,请自己编写;如果经常出现,请将其作为 RFE 报告给 Guava 团队。
  • 我很确定,匹配器在这里有点过头了,因为你只是在创建一个例外,即很少使用的东西(我希望)。由于您的测试只是运行时,它无法真正帮助捕获错误。如果您可以静态地确保“正确”构造的异常,那就太好了,但在纯 java 中这是不可能的。

更重要的是:您抛出的异常可能不如您在没有所有检查的情况下得到的异常。想象一下,用户提供了一个原因但没有任何消息。您认为这很糟糕,但是您将其替换为没有任何原因的 NPE。那更糟。

看看 Guava 的Preconditions.format(包私有)。他们可以首先检查参数的正确数量,但他们没有。您可以提供太少或太多,这是一个错误,但忽略它是最好的处理方法。

【讨论】:

  • 用户不应该创建一个有原因但没有消息的异常,这就是我试图在框架范围内建立的合同......
  • 我知道...但是 1. 你不能阻止他们这样做(也许通过 FindBugs 之类的东西你可以;也许物理威胁会这样做)。 2. 当他们这样做时,你不能让它变得更好,只会变得更糟(除了你的例外,你失去了按摩原因原始异常类型)。 3.如果要提供原因,不能使用Preconditions,必须自己运行。
猜你喜欢
  • 1970-01-01
  • 2020-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多