本文来自《Java核心技术》

为什么需要断言

比如你想要假设某个条件符合的时候再来进行从操作,比如数值为非负或者文件存在又或者字符串不为空,我们可以用判断语句,如果条件不满足的时候,可以抛出异常。这样做似乎没什么问题,但是,如果这样的语句太多了的话就会充斥在代码当中,而且会导致程序的执行速度变慢。如果只是测试时需要,而发布时又不需要,那么这些代码是去不掉的,这个时候断言就起作用了。

什么是断言

断言机制允许在测试的期间向代码中插入一些查询语句。当代码发布时,这些插入的检测语句将会被移走。

断言使用形式

java中引入了关键字assert。

  1. assert 条件;
  2. assert 条件:表达式;

这两种形式都会对条件进行检测,如果结果为false,则抛出一个AssertError异常。在第二种形式中,表达式将被传入AssertionError的构造器,并装换成一个消息字符串。

表达式部分的唯一目的就是产生一个消息字符串。AssertionError对象并不存储表达式的值,因此,不可能在以后得到它。

JDK文档中描述的是:如果使用表达式的值,就会鼓励程序员试图从断言中恢复程序的运行,这不符合断言机制的初衷。

启用和禁用断言

在默认情况下,断言是被禁用的。可以在程序运行时用-enableassertions-ea选项启用它:

java -enableassertions MyApp

启用或者禁用断言不必重新编译程序。启动或者禁用断言是类加载器的功能。当断言被禁用时,类加载器将跳过断言代码,因此,不会降低程序的运行速度。

也可以在某个类或者某个包中使用断言,例如:
java -ea:MyClass -ea:com.mycompany.mylib... MyApp

这条命令将开启MyClass类以及在com.mycompany.mylib包和它的子包中的所有类的断言。选项-ea将开启默认包中的所有类的断言。

也可以使用-disableassertions或-da禁用某个特定的类和包的断言:
java -ea:... -da:MyClass MyApp

有些类不是由类加载器加载,而是直接由虚拟机加载。可以使用这些开关有选择地启用或禁用哪些类中的断言。
然而,启用和禁用所有断言的-ea和-da开关并不能应用到那些没有类加载器的“系统类”上。对于这些系统类而言,需要使用-enablesystemassertions/-esa开关启动断言。

使用断言完成参数检查

java中的3中处理系统错误的机制:

  • 抛出一个异常
  • 日志
  • 使用断言

什么时候应该使用断言呢?

  • 断言失败是致命的、不可恢复的错误
  • 断言检查只用于开发和测试阶段

因此,不应该使用断言向程序的其他部分通告发生了可恢复性的错误,或者,不应该作为程序向用户通告问题的手段。断言只应该是在测试阶段确定程序内部错误的位置。

断言是一种测试和调试阶段所使用的战术性工具;而日志记录是一种在程序的整个生命周期都可以使用的策略性工具。

public class App 
{
    public static void main( String[] args )
    {
        int a = -1;
        assert a > 0 : "liuni是笨蛋";
        System.out.println( "Hello World!" );
    }
}