我什么时候应该使用Apache Commons的Valid.isTrue,什么时候我应该只使用'assert'关键字?

2022-09-05 00:19:15

我什么时候应该使用Apache Commons的Valid.isTrue,什么时候我应该只使用'assert'关键字?


答案 1

Validate.isTrue 和“assert” 服务于完全不同的目的。

assert
Java的assert语句通常用于记录(通过断言)在什么情况下可以调用方法,以及它们的调用者可以期望在什么情况下是正确的。可以选择在运行时检查断言,如果断言不成立,则会导致断言错误异常。

就合同设计而言,断言可用于定义前置和后置条件以及类不变量。如果在运行时检测到这些不成立,则表明系统中存在设计或实现问题。

Validate.isTrue
org.apache.commons.lang.Validate 是不同的。它提供了一组简单的类似JUnit的方法,这些方法检查条件,如果条件不成立,则抛出“IllegalArgumentException”。

它通常在公共 API 应该容忍不良输入时使用。在这种情况下,其合约可以承诺在错误输入时抛出非法争议。Apache Validate为实现这一点提供了一个方便的简写。

由于抛出了一个非法的参数,因此使用Apache的Valid来检查后置条件或不变量是没有意义的。同样,使用“assert”进行用户输入验证是不正确的,因为可以在运行时禁用断言检查。

但是,使用两者
是可能的,尽管用于不同的目的,但可以同时使用两者。在这种情况下,合同应明确要求根据某些类型的输入提出非法争议异常。然后通过Apache Validate实现。然后简单地断言不变量和后置条件,以及可能的附加前提条件(例如影响对象的状态)。例如:

public int m(int n) {
  // the class invariant should hold upon entry;
  assert this.invariant() : "The invariant should hold.";

  // a precondition in terms of design-by-contract
  assert this.isInitialized() : "m can only be invoked after initialization.";

  // Implement a tolerant contract ensuring reasonable response upon n <= 0:
  // simply raise an illegal argument exception.
  Validate.isTrue(n > 0, "n should be positive");

  // the actual computation.
  int result = complexMathUnderTrickyCircumstances(n);

  // the postcondition.
  assert result > 0 : "m's result is always greater than 0.";
  assert this.processingDone() : "processingDone state entered after m.";
  assert this.invariant() : "Luckily the invariant still holds as well.";

  return result;
}

更多信息:

  • Bertrand Meyer, “Apply Design by Contract”, IEEE Computer, 1992 (pdf)
  • 乔苏亚布洛赫。《有效Java》,第2版,第38项。检查参数的有效性。(谷歌图书)

答案 2

断言可以关闭(实际上,它们通常是关闭的),因此它们对于验证用户输入没有用,例如。


推荐