assert
关键字像其名称所示,对代码进行了一项
断言。它用于指定始终为真的某些内容——或者至少应该是真的!
assert
关键字后面跟着一个布尔值(
true
或
false
),或者在运行时要评估返回布尔值的表达式。
assert true;
assert 1 == 1;
如果由于任何原因布尔表达式计算结果为false,则会抛出一个AssertionError
。
// this will throw an AssertionError:
int x = 1
assert x == 2
当您使用 `assert` 时,您会对程序在给定点上的状态做出明确的陈述,这可以使读者更容易跟随您的代码。
有一种名为“按契约编程”的编程范式,在该范式中,代码片段对必须满足的前提条件以及执行后保证成立的后置条件进行声明。您可以使用 `assert` 关键字来实现这一点。
例如,如果您编写了一个计算数字平方根的方法,它只适用于大于或等于零的数字,并且结果保证满足相同的条件:
public double sqrt(final double x) {
assert x >= 0 : "Cannot calculate the square root of a negative number!"
double result = ...;
assert result >= 0 : "Something went wrong when calculating the square root!"
return result;
}
断言最有趣的方面是您可以要求编译器从字节码中删除它们(通过-disableassertion
参数),以便在生产时不会出现任何运行时性能损失。因此,极其重要的是,要评估的表达式不会引起副作用,也就是说,该表达式应该像纯数学函数一样。否则,如果编译器删除了您的断言,则程序的行为可能会发生变化。
最后,如果断言被编译到字节码中,它们可以被软件读取,该软件将自动生成测试,试图破坏您的代码。这可能有助于更早地发现错误!
AssertionError
,它是Error
的子类,而Error
又是Throwable
的子类。Exception
是Throwable
的另一个子类,但具有不同的语义。你可以将Error
视为比Exception
更糟糕的东西。异常存在的目的是让你将“主要代码”与处理运行时可能发生的问题的代码(例如 IOException)分开。当发生更严重且通常无法恢复的情况时,例如 OutOfMemoryError 或 StackoverflowError 时,就会抛出错误。 - Bruno ReisAssertionError
,因为这意味着你的代码没有被正确使用(即必须满足的前提条件并没有完全满足!)。 - Bruno ReisPreconditions
的类,其中有静态方法接受表达式和字符串,并且几乎像assert
关键字一样工作。主要区别是:(1)Guava将抛出未经检查的异常而不是AssertionError;(2)这些方法具有更多语义化的名称,例如Preconditions.checkNotNull(myParameter);(3)它们不能被编译器自动删除。 - Bruno Reisjavac -disableassertion MyClass.java
。该参数本身可以接受参数,因此您可以有选择地在某些类上禁用断言,并在其他类上启用它们。 - Bruno Reis