ThinkSSL🔒 一键申购 5分钟快速签发 30天无理由退款 购买更放心 广告
#### [Java 断言语法](https://lingcoder.gitee.io/onjava8/#/book/16-Validating-Your-Code?id=java-%e6%96%ad%e8%a8%80%e8%af%ad%e6%b3%95) 你可以通过其它程序设计架构来模拟断言的效果,因此,在 Java 中包含断言的意义在于它们易于编写。断言语句有两种形式 : assert boolean-expression; assert boolean-expression: information-expression; 两者似乎告诉我们**“我断言这个布尔表达式会产生 true”**, 否则,将抛出**AssertionError**异常。 **AssertionError**是**Throwable**的派生类,因此不需要异常说明。 不幸的是,第一种断言形式的异常不会生成包含布尔表达式的任何信息(与大多数其他语言的断言机制相反)。 下面是第一种形式的例子: ~~~ // validating/Assert1.java // Non-informative style of assert // Must run using -ea flag: // {java -ea Assert1} // {ThrowsException} public class Assert1 { public static void main(String[] args) { assert false; } } /* Output: ___[ Error Output ]___ Exception in thread "main" java.lang.AssertionError at Assert1.main(Assert1.java:9) */ ~~~ 如果你正常运行程序,没有任何特殊的断言标志,则不会发生任何事情。你需要在运行程序时显式启用断言。一种简单的方法是使用**\-ea**标志, 它也可以表示为:**\-enableassertion**, 这将运行程序并执行任何断言语句。 输出中并没有包含多少有用的信息。另一方面,如果你使用**information-expression**, 将生成一条有用的消息作为异常堆栈跟踪的一部分。最有用的**information-expression**通常是一串针对程序员的文本: ~~~ // validating/Assert2.java // Assert with an information-expression // {java Assert2 -ea} // {ThrowsException} public class Assert2 { public static void main(String[] args) { assert false: "Here's a message saying what happened"; } } /* Output: ___[ Error Output ]___ Exception in thread "main" java.lang.AssertionError: Here's a message saying what happened at Assert2.main(Assert2.java:8) */ ~~~ **information-expression**可以产生任何类型的对象,因此,通常将构造一个包含对象值的更复杂的字符串,它包含失败的断言。 你还可以基于类名或包名打开或关闭断言;也就是说,你可以对整个包启用或禁用断言。实现这一点的详细信息在 JDK 的断言文档中。此特性对于使用断言的大型项目来说很有用当你想打开或关闭某些断言时。但是,日志记录(*Logging*)或者调试(*Debugging*),可能是捕获这类信息的更好工具。 你还可以通过编程的方式通过链接到类加载器对象(**ClassLoader**)来控制断言。类加载器中有几种方法允许动态启用和禁用断言,其中**setDefaultAssertionStatus ()**,它为之后加载的所有类设置断言状态。因此,你可以像下面这样悄悄地开启断言: ~~~ // validating/LoaderAssertions.java // Using the class loader to enable assertions // {ThrowsException} public class LoaderAssertions { public static void main(String[] args) { ClassLoader.getSystemClassLoader(). setDefaultAssertionStatus(true); new Loaded().go(); } } class Loaded { public void go() { assert false: "Loaded.go()"; } } /* Output: ___[ Error Output ]___ Exception in thread "main" java.lang.AssertionError: Loaded.go() at Loaded.go(LoaderAssertions.java:15) at LoaderAssertions.main(LoaderAssertions.java:9) */ ~~~ 这消除了在运行程序时在命令行上使用**\-ea**标志的需要,使用**\-ea**标志启用断言可能同样简单。当交付独立产品时,可能必须设置一个执行脚本让用户能够启动程序,配置其他启动参数,这么做是有意义的。然而,决定在程序运行时启用断言可以使用下面的**static**块来实现这一点,该语句位于系统的主类中: ~~~ static { boolean assertionsEnabled = false; // Note intentional side effect of assignment: assert assertionsEnabled = true; if(!assertionsEnabled) throw new RuntimeException("Assertions disabled"); } ~~~ 如果启用断言,然后执行**assert**语句,**assertionsEnabled**变为**true**。断言不会失败,因为分配的返回值是赋值的值。如果不启用断言,**assert**语句不执行,**assertionsEnabled**保持false,将导致异常。