断言使用准则
由于断言应被视为对程序进行验证的一种工具,而不是把它当作程序的一部分,所以你应遵循以下准则。
首先,不适合在公共方法中使用断言参数检查,因为参数检查通常是一个合约的一部分,无论断言是否启用都应该执行。错误发生时,应该引发恰当的运行时异常,比如IndexOutOfBoundsException或者NullPointerException,而不是引发常规的断言错误。
其次,不建议为一个必需的操作使用断言。由于断言可以启用或禁用,所以不应将操作与断言混合。断言只是一种调试工具。例如,下例就会出现问题:
assert names.remove(null);
names.remove(null)本来是程序中的一个有效的语句,在你的算法中应该总是返回true。用断言来检查它虽然可行,但一旦断言被禁用,该语句就会被跳过。所以,无论如何都应该将断言和正确的操作分开,例如:
boolean nullsRemoved = names.remove(null);
assert nullsRemoved;
在断言被启用的前提下,第二个语句检查返回值,第一个语句则总是执行names.remove(null)操作。这样可确保断言不会影响正常操作。
虽然可能要将断言从最终产品中剥离,但没有工具能自动删除不再需要的断言。不过,采取以下方式,也许能帮助你在编译时跳过断言语句:
static final boolean isAssertUsed = true;
if (isAssertUsed) assert MyCondition;
上述代码取代了单行语句assert MyCondition。如果isAssertUsed为true,它会触发断言。如果编译时不需要断言,将isAssertUsed的值变成false就可以了:
static final boolean isAssertUsed = false;
if (isAssertUsed) assert MyCondition;
由于条件isAssertUsed总是为false,所以if内部的内容是一个不可读的区域,编译器会自动跳过这个区域。这称为“条件编译”。进行上述修改并重新编译了代码后,程序的生产版本将不再含有断言。
还建议你在初始化一个类之前,检查断言是否启用。在断言被禁用的情况下,以下代码有助于防止一个类被初始化:
static {
boolean isAssertEnabled = false;
assert isAssertEnabled = true;
if (!isAssertEnabled)
throw new RuntimeException("Assertion must be enabled!");
}
断言启用的前提下,assert isAssertEnabled = true语句可将变量isAssertEnabled设为true。在断言被禁用的前提下,会跳过该语句(变量依然为false)。所以,如果断言是禁用的,就会运行if语句并引发异常。
用断言来验证逻辑
断言是具有重要价值的一种调试工具。它提供了一种清晰和可跟踪的形式来验证程序逻辑。它还提供了一种灵活和独立的策略来帮助你进行开发,而且最终可以从程序的生产版本中拿掉。
