有哪些真实的例子来理解断言的关键作用?


当前回答

Assert是一个关键字。它在JDK 1.4中引入。这是两种类型的断言

非常简单的断言语句 简单的断言语句。

默认情况下,所有assert语句都不会被执行。如果assert语句接收到false,则它将自动引发断言错误。

其他回答

下面是最常见的用例。假设你正在打开一个枚举值:

switch (fruit) {
  case apple:
    // do something
    break;
  case pear:
    // do something
    break;
  case banana:
    // do something
    break;
}

只要你处理每一个案子,就没问题。但是有一天,有人会把fig添加到你的枚举中,而忘记把它添加到你的switch语句中。这将产生一个难以捕捉的错误,因为直到您离开switch语句后才会感受到其影响。但是如果你像这样写开关,你可以立即捕获它:

switch (fruit) {
  case apple:
    // do something
    break;
  case pear:
    // do something
    break;
  case banana:
    // do something
    break;
  default:
    assert false : "Missing enum value: " + fruit;
}

断言(通过assert关键字)是在Java 1.4中添加的。它们用于验证代码中不变量的正确性。它们永远不应该在生产代码中触发,并且指示了代码路径的错误或误用。它们可以在运行时通过java命令上的-ea选项激活,但默认情况下不会打开。

一个例子:

public Foo acquireFoo(int id) {
  Foo result = null;
  if (id > 50) {
    result = fooService.read(id);
  } else {
    result = new Foo(id);
  }
  assert result != null;

  return result;
}

总结一下(不仅仅是Java,很多语言都是如此):

“assert”主要被软件开发人员在调试过程中用作调试辅助。断言消息永远不会出现。许多语言提供了一个编译时选项,该选项将导致所有“断言”被忽略,用于生成“生产”代码。

"exceptions" are a handy way to handle all kinds of error conditions, whether or not they represent logic errors, because, if you run into an error-condition such that you cannot continue, you can simply "throw them up into the air," from wherever you are, expecting someone else out there to be ready to "catch" them. Control is transferred in one step, straight from the code that threw the exception, straight to the catcher's mitt. (And the catcher can see the complete backtrace of calls that had taken place.)

此外,该子例程的调用者不必检查子例程是否成功:“如果我们现在在这里,它一定成功了,因为否则它会抛出异常,我们现在就不会在这里!”这种简单的策略使得代码设计和调试变得非常非常容易。

异常方便地允许致命错误条件保持原样:“规则的异常”。而且,对于它们来说,由代码路径来处理,这也是“规则的例外……“高飞球!”

断言是可以被关闭的检查。它们很少被使用。为什么?

它们不能用于检查公共方法参数,因为您无法控制它们。 它们不应该用于简单的检查,如result != null,因为这样的检查非常快,几乎没有什么可以保存。

那么,还剩下什么呢?昂贵的条件检查是真实的。像rb树这样的数据结构的不变量就是一个很好的例子。实际上,在JDK8的ConcurrentHashMap中,对于TreeNodes有一些这样有意义的断言。

您确实不希望在生产环境中启用它们,因为它们很容易控制运行时间。 您可能希望在测试期间打开或关闭它们。 在处理代码时一定要打开它们。


有时候,支票不是很贵,但与此同时,你很确定,它会通过。在我的代码中,有例如,

assert Sets.newHashSet(userIds).size() == userIds.size();

我很确定我刚刚创建的列表有独特的元素,但我想记录并再次检查它。

断言用于检查后置条件和“永不失败”的前提条件。正确的代码应该永远不会使断言失败;当它们触发时,它们应该指出一个错误(希望是在接近问题的实际位置的地方)。

断言的一个例子可能是检查一组特定的方法是否以正确的顺序被调用(例如,在迭代器中hasNext()在next()之前被调用)。