帮你调试-Java1.4-assertions,断言使你的代码更加稳定

用assertions使你的代码更加稳定

了解Java的assertions(断言)性能是怎样为开发人员提供更好的方法来创建稳定的、高质量的、易调试的代码的。
by Josh Street

或许你还没有注意到,Sun Microsystems已经将一个新的关键字添加到Java语言中去了。这个assert关键字是由JSR41 -- 一个最终将真正的assertions性能添加到Java中去的Java Specification Request提出的。由于这个新的assert关键字和大多数C/C++开发人员所熟悉的用法有很大的区别,因此详细地了解它一定会使你有所受益。

Java的assertions特性用于一个特殊的目的:当用户定义的布尔表达式为False时它会抛出一个错误。更确切地说,一个assertion被当作一个发现某个值变成false的信号,它用来指示当前函数需要被中断。该性能被用在创建不该出现在真正产品部署过程中的专用调试模式上时非常有用。

开启 Assertion
在使用assertions之前,你需要开启(enable)它们,因为Java Runtime Environment (JRE)会自动将所有的assertions关闭。你可以用–enableassertions 标记(flag)(缩写是–ea)来开启它;同样,用–disableassertions 标记(缩写是–da)来关闭它。你可以使用一些同时带有这两个标记的选项:

no arguments是指该标记适用于所有assertions。
packageName...是指该标记适用于packageName包及其子包中的所有类。
...是指该标记适用于当前目录下的未命名的(缺省的)包。
className是指该标记只适用于className

看以下这个命令行:

java -ea:foo.bar... -da:foo.bar.old MyClass

它用于开启除了foo.bar.old之外的foo.bar包及其子目录中的assertions。

如何及何时使用Assertion
一个Java assertion有两种形式。第一种形式经实践证明是可取的:

assert some_boolean_expression;

这就是说如果some_boolean_expression的值是false,则会被抛出一个AssertionError。注意这是一个错误,而不是一个异常;同样地,它被当作一个非检查异常(unchecked exception)来对待。(想要了解更多关于错误和异常之间的区别,请查阅我的另一篇文章“错误与异常”。)

另一种更为复杂形式的assert语句提供了一些更多的功能:

assert some_boolean_expression : 
   some_non-void_expression

这种形式比其前一种来说更加有用。第二个表达式some_non-void_expression被传入用于AssertionError的构造器中。它能够显示更多发生在assertion失败时的信息。注意第二个参数可能会是任何对象或基本类型(包括null)。

列表1提供了一个简单的使用第二种assert语句形式的范例。由于AssertionError是一个非检查异常,所以没必要去捕获它(在列表1中由于示范说明的原因而对它进行了捕获)。实际上,忽略(不去捕获)AssertionErrors可能看起来也挺好,但你不应该这么做,因为这样一来可能会使应用程序处于一种不稳定的状态下,尤其是对一个Swing-based程序来说更是如此。

有一些不能使用assertions的情况,比如试着用以下代码找到问题:

assert isValid( myObject );

尽管这么做看起来像是一个好办法,但是想想看当assertion关闭时该怎么办――记住这是它的缺省状态:这个isValid方法将无法执行!特别是,一些行为(方法、操作等等)不能被用于这个assert语句的第一个参数,因为(除非有其他特别指定)它将永远无法执行。

你可能想知道如何编写开启assertions的代码,虽然这并不是一个好主意,但它会对已知的有依赖关系(dependency)的代码很有帮助。为此Sun提供了这个小技巧:

    boolean assertsEnabled = false; 
     // here's the trick
       assert assertsEnabled = true;
    if( !assertsEnabled )
        throw new RuntimeException(
           "Asserts must be enabled!");
}

你可以将这段代码用于任何需要开启assertion的静态初始化类中。如果assertion是关闭的,那么assert语句将无法执行并会抛出一个异常;否则便会继续执行,条件失效。

解决兼容性问题
Java的assertion功能是一个语言特性,而不是API性能的扩展。Assertions代表了Java语言在多个版本间的首次显著的改变但同时也将二进制兼容性的问题带了回来。这就意味着编译到支持assertions的程序将无法在老版本JRE中运行。为了使开发人员更容易地创建带有assertions的程序,Sun采取了谨慎的方法。JDK 1.4版本中程序的缺省状态是不支持assertion的,而用assertions编译的代码会产生以下响应:

warning: as of release 1.4, assert is a 
keyword, and may not be used as an identifier

除了这个warning以外,使用assert关键字还会导致许多编译错误。为了实现用assertions来编译程序,你需要使用一个–source 1.4标记。比如,在列表1中显示的编译命令代码:

javac -source 1.4 Assert.java

Java新的assertion功能为开发人员使用先进的技术(比如Design By Contract)来创建稳定的、高质量的代码提供了新的方法。你需要考虑我提到的问题,但我想你也会认同这个新功能在Java语言中是相当受欢迎的

--列表1---.

用assert进行检测

列表1.这个简单的范例用来示范如何使用assertions来检测那些可预知但不理想的结果。

public class Assert
{
   public static void main(String[] args)
   {
      try
      {
         doSomething();
      }
      catch(AssertionError error)
      {
         error.printStackTrace();
      }
   }
   public static int doSomething()
   {
      int i = 2;
      assert i != 2 : "i was 2 for some reason";
      return i;
   }
}



关于作者:
Josh Street是Bank of America的方案架构师。你可以通过 [email protected]和他联系。

你可能感兴趣的:(Java,基础)