有哪些现实的例子可以理解断言的关键作用?
断言(通过assert关键字)是在Java 1.4中添加的。它们用于验证代码中不变式的正确性。切勿在生产代码中触发它们,并表示存在错误或滥用代码路径。可以在运行时通过命令-ea上的选项将其激活java,但默认情况下未启用它们。
-ea
java
一个例子:
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; }
让我们假设你应该编写一个程序来控制核电站。很明显,即使是最轻微的错误也可能导致灾难性的结果,因此你的代码必须没有错误(假设出于参数考虑,JVM是没有错误的)。
Java不是可验证的语言,这意味着:你无法计算出操作的结果是否完美。这样做的主要原因是指针:它们可以指向任何地方或任何地方,因此无法计算出具有确切值的指针,至少不在合理的代码范围内。鉴于此问题,没有办法证明你的代码总体上是正确的。但是你可以做的是证明你至少在发现每个错误时都会发现它。
这个想法是基于按合同设计(DbC)范式的:你首先(以数学精度)定义方法应该执行的操作,然后通过在实际执行过程中对其进行测试来进行验证。例:
// Calculates the sum of a (int) + b (int) and returns the result (int). int sum(int a, int b) { return a + b; }
尽管这显然可以正常工作,但大多数程序员不会在其中发现隐藏的错误(提示:Ariane V因类似的错误而崩溃)。现在,DbC定义你必须始终检查函数的输入和输出以验证其是否正常工作。Java可以通过断言来做到这一点:
// Calculates the sum of a (int) + b (int) and returns the result (int). int sum(int a, int b) { assert (Integer.MAX_VALUE - a >= b) : "Value of " + a + " + " + b + " is too large to add."; final int result = a + b; assert (result - a == b) : "Sum of " + a + " + " + b + " returned wrong sum " + result; return result; }
如果此功能现在失败,你将注意到它。你将知道代码中存在问题,知道问题出在哪里,并且知道是什么原因引起的(类似于Exceptions)。更重要的是:你会在发生错误时停止正确执行,以防止任何其他代码使用错误的值运行,并可能损坏其控制的内容。
Java异常是一个类似的概念,但是它们无法验证所有内容。如果要进行更多检查(以执行速度为代价),则需要使用断言。这样做会使你的代码膨胀,但是最终你可以在出乎意料的短开发时间内交付产品(越早修复错误,成本越低)。另外:如果你的代码中有任何错误,你将对其进行检测。没有任何漏洞可以通过,并在以后引起问题。
这仍然不能保证没有错误的代码,但是比通常的程序更接近于此。