【自学】Java核心技术卷1_7.4断言
- 断言(Assertion)是Java中一条语句,包含一个布尔表达式,当该布尔值为真,程序则被认为是正确的;当布尔值为假,则系统会抛出错误。
- 断言机制允许在测试期间向代码中插入一些检查语句,当代码发布时,这些插入的检测语句将会被自动移走
断言的形式
1)assert condition; // assert x>=0;
- condition是一个boolean表达式,如果condition为true则断言为真,程序继续执行
- 如果condition为false,则断言失败,抛出AssertionError对象,终止执行程序
- 如果在执行condition时,condition本身抛出Exception,则assert停止运行,抛出异常
2)assert condition:expr; //assert x>=0:x;
- expr可以是基本类型或者任意对象,通常用于断言失败后的提示信息,即将expr传入AssertionError的构造器,并转换成一个消息字符串显示出来(表达式的唯一目的是产生一个消息字符串,AssertionError对象不存储表达式的值,不可能在以后得到表达式)
启用和禁用断言
- 默认情况断言被禁用;
- -enableassertions或-ea选项启用断言;-disableassertions或-da禁用断言
- 启用或禁用断言时不必重新编译程序,启用或禁用断言是类加载器(class loader)的功能,禁用断言时类加载器将跳过断言代码
- 断言可以局部开启,如父类禁用断言,子类可以开启断言,一般说“断言不具有继承性”
1)参数 -esa和 -dsa含义为开启(关闭)系统类的assertion功能。-esa和-dsa的全名为-enablesystemassertions和-disenablesystemassertions,全名和缩写名有同样的功能。
2)参数 -ea和 -da含义为开启(关闭)用户类的assertion功能。-ea和-da的全名为-enableassertions和-disenableassertions,全名和缩写名有同样的功能。
- 如果不带任何参数,表示开启(关闭)所有用户类;
- 如果带有包名称或者类名称,表示开启(关闭)这些类或包;
- 如果包名称后面跟有三个点,代表这个包及其子包;
- 如果只有三个点,代表无名包。
参数使用举例(-ea和-da用法一样,-esa和-dsa同理) |
||
参数 |
例子 |
说明 |
-ea |
java -ea |
打开所有用户类的assertion |
-ea: |
java -ea:MyClass1 |
打开MyClass1的assertion |
-ea: |
java -ea:pkg1 |
打开pkg1包的assertion |
-ea:... |
java -ea:... |
打开缺省包(无名包)的assertion |
-ea:... |
java -ea:pkg1... |
打开pkg1包和其子包的assertion |
-esa |
java -esa |
打开系统类的assertion |
综合 |
java -dsa:MyClass1:pkg1 |
关闭MyClass1和pkg1包的assertion |
选择使用断言的原则
- 断言失败是致命的、不可恢复的错误
- 断言检查只用于开发和测试阶段
- 断言只应该用于在测试阶段确定程序内部的错误位置,必须不依赖它们完成任何程序实际所需的行为,即assert语句不构成程序正常运行逻辑的一部分(如不应该使用断言向程序的其他部分通告发生了可恢复性的错误;且断言不能作为程序向用户通告问题的手段——因为正常发布的代码都是断言无效的)
- 断言语句的作用是保证程序内部的一致性,而不是用户和程序之间的一致性,所有不应用在保证命令行参数的正确性
断言使用场景
- 变量值明确。变量值如果很确定是某个值,则可以使用断言
- 执行不到的语句。某个地方语句确定是执行不会达到的,例如没有default的switch,则default可加上断言
- 前置条件。前置条件是一条语句,在方法执行前必须为真,否则不应该使用方法,也不能启动方法能正确执行。前置条件可以与方法参数的描述相关。
- 后置条件。后置条件是一条语句,当前置条件满足且完全执行方法后,它为真。后置条件一般描述方法调用产生的所有影响,有助于弄清楚方法的目的,不满足后置条件的方法,即使满足前置条件,也可以抛出异常。
- 检查类的状态。加一个内部方法,返回布尔值,当检查类状态正常时,返回true
不要用断言的场景
- 不要用断言做参数检查。因为无论断言是启用还是禁用,都必须进行参数检查,而断言是可能被禁用的。并且断言报出的AssertionError异常不能准确反馈运行时异常
- 不要用断言完成程序正确操作所需的任何工作。因为正常发布的程序不执行断言语句
- 在对外公开的方法中不要使用断言。(防御式编程)
Java为了让程序也能够动态开启和关闭某些类和包的assertion功能,Java修改了Class和ClassLoader的实现,增加了几个用于操作assert的API:
代码练习Intellij使用断言:
没开断言时,跳过assert语句:
Intellij启用断言:
public class AssertTest {
public static void main(String args[]){
boolean condition1=1>0;
assert condition1;
System.out.println("condition1 is true");
boolean condition2=1>2;
try{
assert condition2:"condition2 is false";
System.out.println("condition2 is true");
}catch(AssertionError err){
System.out.println(err.getMessage());
}
}
}