大可制作:QQ群:31564239(asp|jsp|php|mysql)

Java Gossip: 断言(Assertion)

异常是程序中非预期的错误,异常处理是在这些错误发生时所采取的措施。

有些时候,您预期程序中应该会处于何种状态,例如某些情况下某个值必然是多少,这称之为一种断言(Assertion),断言有两种情况:成立或不成立。当预期结果与实际执行相同时,断言成立,否则断言失败。

Java在JDK 1.4之后提供断言陈述,有两种使用的语法:
assert <boolean_expression>;
assert <boolean_expression> : <detail_expression>;

boolean_expression如果为true,则什么事都不会发生,如果为false,则会发生 java.lang.AssertionError,此时若采取的是第二个语法,则会将detail_expression的结果显示出来,如果是个对象,则调用它的toString()显示文字描述结果。

一个使用断言的时机是内部不变量(Internal invarant)的判断,例如在某个时间点上,或某个状况发生时,您判断某个变量必然要是某个值,举个例子来说:

  • AssertionDemo.java
public class AssertionDemo {
public static void main(String[] args) {
if(args.length > 0) {
System.out.println(args[0]);
}
else {
assert args.length == 0;
System.out.println("没有输入参数");
}
}
}

在正常的预期中,数组长度是不会小于0的,所以一但执行至else区块,数组长度必然只有一个可能,就是等于0,您断言args.length==0结果 必然成立,else之中的程序码也只有在断言成立的状况下才能执行,如果不成立,表示程序运行存在错误,else区块不应被执行,您要停下来检查程序的错 误,事实上断言主要的目的通常是在开发时期才使用。

断言功能是在JDK 1.4之后提供的,由于断言使用assert作为关键字,为了避免您以前在JDK 1.3或更早之前版本的程序使用了assert作为变量,而导致的名称冲突问题,默认上执行时是不启动断言检查的,如果您要在执行时启动断言检查,可以使用-enableassertions或是-ea参数,例如:

 java -ea AssertionDemo

您可以启用断言,但选择性的使用-disableassertions或-da关闭某些类中的断言机制,例如关闭onlyfun.caterpillar.Foo类中的断言:
 java -ea -da:onlyfun.caterpillar.Foo AssertionDemo

或是选择性的使用-disableassertions或-da关闭某些包中的断言机制,例如关闭onlyfun.caterpillar包中的断言:
 java -ea -da:onlyfun.caterpillar... AssertionDemo


另一个使用断言的时机为控制流程不变量(Control flow invariant)的判断,例如在使用switch时,假设您已经列出了所有的可能常量:
...
switch(var) {
    case Constants.Con1:
        ...
        break;
    case Constants.Con2:
        ...
        break;
    case Constants.Con3:
        ...
        break;
    default:
        assert false : "非定义的常量";
}
...

假设您已经在switch中列出了所有的常量,即var不该出现Constants.Con1、Constants.Con2、 Constants.Con3以外的常量,则如果发生default被执行的情况,表示程序的状态与预期不符,此时由于assert false必然断言失败。

总结就是,断言是判定程序中的某个执行点必然是某个状态,所以它不能当作像if之类的判断式使用,简单的说它不应是程序执行流程的一部份。