整理自:
java基础之断言细谈(比较清楚和全面,可先看这个博客!!!)
java assert断言的用法
java断言机制
Java断言机制
java断言机制(assert)
Java核心技术 卷I
断言与异常(Assertion Vs Exception)(区别断言和异常的使用场景!!!)
!另附JUnit中Assert简单介绍
一、何为断言
断言机制:允许java开发者在代码中加入一些检查语句,主要用于程序调试
目的。
1.断言机制在用户定义的boolean表达式结果为false时抛出一个error对象,其类型为AssertionError;
2.当我们需要在约定的条件不成立时中断当前操作的话,可以使用断言;
3.作为Error的一种,断言失败可不捕获处理或者声明抛出,一旦出现了则终止程序、不必进行补救或恢复
。
assert关键字是在JDK1.4
才被添加,用于程序的调试
。用法有两种:
1.assert expression1;
expression1是逻辑运算表达式
,如果expression1为true,表示断言成功,程序继续执行。如果为false,会抛出AssertionError,AssertionError继承Error类,Error类与我们经常用到的Exception类都是集成于Throwable类。AssertionError由于是错误,所以可以不捕获,但不推荐这样做,因为那样会使你的系统进入不稳定状态。
public static void main (String[] args) {
boolean flag = 1>2;
assert flag;
}
2.assert expression1:expression2;
用法与1相同,但添加了表达式expression2,当AssertionError发生时,该表达式将被传入AssertionError的构造器,并转换成一个消息字符串。
public static void main (String[] args) {
boolean flag = 1>2;
assert flag : "flag is false";
}
注意:
1、一种特殊情况是,如果在计算表达式时,表达式本身抛出Exception,那么assert将停止运行,而抛出这个Exception。
2、Expression2的唯一目的是产生一个消息字符串,AssertionError对象并不存储表达式Expression2的值,因此你不可能在以后获取它。
使用assert 我们不用再调试时使用if或System.out来输出调试信息,当程序正式发布就不用再去删除这些调试信息了。而assert可以通过参数-da(默认)使程序不进行断言判断
。
二、启用和禁用断言
本部分可详见《Java核心技术 I》P286
默认情况下,断言被禁用。
可以在运行程序时用-enableassertions
或-ea
选项启用:java -enableassertions MyAppClass
或java -ea MyAppClass
。
也可用选项-disableassertions
或-da
禁用断言:java -disableassertions MyAppClass
或java -da MyAppClass
。
需要注意的是,在启用或禁用断言时,不必重新编译程序。启用或禁用断言是类加载器的功能。当断言被禁用时,类加载器将跳过断言代码。
java -ea:MyClass -ea:com.mycompany.mylib… MyApp
用于开启MyClass类以及在com.mycompany.mylib包及其子包中所有类的断言;
java -ea:… -da:MyClass MyApp
开启默认包中除MyClass类的断言。???
然而, 启用和禁用所有断言的-ea
和-da
开关不能应用到那些没有类加载器的“系统类”上。对于这些系统类来说,需使用-enablesystemassertions/-esa
开关启用断言。
在eclipse当中:run configurations->arguments->vm arguments中添加 -ea
三、断言使用
Java中有3种处理系统错误的机制:
- 抛出异常
- 日志
- 使用断言
关于断言,牢记:
- 断言失败是致命的、不可恢复的错误;
- 断言检查只用于开发和测试阶段。
Java断言的特点是:断言失败时会抛出AssertionError,导致程序结束退出。因此,断言不能用于可恢复的程序错误,只应该用于开发和测试阶段程序内部错误定位。
对于可恢复的程序错误,不应该使用断言。例如:
void sort(int[] arr) {
assert arr != null;
}
应该抛出异常并在上层捕获:
void sort(int[] arr) {
if (x == null) {
throw new IllegalArgumentException("array cannot be null");
}
}
常见的断言特性:
- 前置条件断言:代码执行之前必须具备的特性
- 后置条件断言:代码执行之后必须具备的特性
- 前后不变断言:代码执行前后不能变化的特性
断言使用场景:
- 变量值明确
变量值如果很确定是某个值,则可以用断言。 - 执行不到的语句
可在正常情况下程序不会到达的地方放置断言,例如没有default的switch,则default可加上断言。 - 测试前置条件、后置条件
- 检查类的状态
加一个内部方法,返回布尔值,当检查类状态正常时返回true。
不要用断言场景:
- 不要用断言做参数检查
因为无论断言是启用还是禁用,都必须进行参数检查的,而断言是可能被禁用的。并且断言报出的AssertionError异常,不能准确反馈运行时异常(例如IllegalArgumentException,IndexOutOfBoundsException或NullPointerException)。 - 不要用断言来完成程序正确操作所需的任何工作
例如,假设你想要从列表名称中删除所有空元素,并且知道该列表包含一个或多个空值。
错误做法:
assert names.remove(null); //行为包含在断言中,当断言被启用时,程序会正常工作,但在禁用时会失败,因为它不再从列表中删除空元素。
正确做法:
boolean nullsRemoved = names.remove(null); assert nullsRemoved; //动作先于断言