`

Java中assert关键字的实现

 
阅读更多

Javaassert关键字的实现

 

J2SE 1.4在语言上提供了一个新特性,就是assertion(断言)功能,它是该版本在Java语言方面最大的革新。在软件开发中,assertion是一种经典的调试、测试方式。

assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制,如CC++Eiffel等,但是支持的形式不尽相同,有的是通过语言本身、有的是通过库函数等。另外,从理论上来说,通过assertion方式可以证明程序的正确性,但是这是一项相当复杂的工作,目前还没有太多的实践意义。

  在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后,assertion检查通常是关闭的。下面简单介绍一下Javaassertion的实现。

  1.1) 语法表示

  在语法上,为了支持assertionJava增加了一个关键字assert。它包括两种表达式,分别如下:

  assert expression1;

  assert expression1: expression2;

  在两种表达式中,expression1表示一个boolean表达式,expression2表示一个基本类型或者是一个对象(Object) ,基本类型包括boolean,char,double,float,intlong。由于所有类都为Object的子类,因此这个参数可以用于所有对象。

  1assert

  如果为true,则程序继续执行。

  如果为false,则程序抛出AssertionError,并终止执行。

  2assert : <错误信息表达式>

  如果为true,则程序继续执行。

  如果为false,则程序抛出java.lang.AssertionError,并输出<错误信息表达式>

  1.2) 语义含义

  在运行时,如果关闭了assertion功能,这些语句将不起任何作用。如果打开了assertion功能,那么expression1的值将被计算,如果它的值为false,该语句强抛出一个AssertionError对象。如果assertion语句包括expression2参数,程序将计算出expression2的结果,然后将这个结果作为AssertionError的构造函数的参数,来创建AssertionError对象,并抛出该对象;如果expression1值为trueexpression2将不被计算。

  一种特殊情况是,如果在计算表达式时,表达式本身抛出Exception,那么assert将停止运行,而抛出这个Exception

  1.3) 一些assertion例子

  下面是一些Assert的例子。

  assert  0 < value;

  assert  0 < value:"value="+value;

  assert  ref != null:"ref doesn''t equal null";

  assert  isBalanced();

  1.4) 编译

  由于assert是一个新关键字,使用老版本的JDK是无法编译带有assert的源程序。因此,我们必须使用JDK1.4(或者更新)Java编译器,在使用Javac命令时,我们必须加上-source 1.4作为参数。-source 1.4表示使用JDK 1.4版本的方式来编译源代码,否则编译就不能通过,因为缺省的Javac编译器使用JDK1.3的语法规则。

  一个简单的例子如下:

  javac -source 1.4 test.java

  1.5) 运行

  由于带有assert语句的程序运行时,使用了新的ClassLoaderClass类,因此,这种程序必须在JDK1.4(或者更高版本)JRE下运行,而不能在老版本的JRE下运行。

  由于我们可以选择开启assertion功能,或者不开启,另外我们还可以开启一部分类或包的assertion功能,所以运行选项变得有些复杂。通过这些选项,我们可以过滤所有我们不关心的类,只选择我们关心的类或包来观察。下面介绍两类参数:

  参数 -esa -dsa

  它们含义为开启(关闭)系统类的assertion功能。由于新版本的Java的系统类中,也使了assertion语句,因此如果用户需要观察它们的运行情况,就需要打开系统类的assertion功能,我们可使用-esa参数打开,使用 -dsa参数关闭。 -esa-dsa的全名为-enablesystemassertions-disenablesystemassertions,全名和缩写名有同样的功能。

  参数 -ea -ea

  它们含义为开启(关闭)用户类的assertion功能:通过这个参数,用户可以打开某些类或包的assertion功能,同样用户也可以关闭某些类和包的assertion功能。打开assertion功能参数为-ea;如果不带任何参数,表示打开所有用户类;如果带有包名称或者类名称,表示打开这些类或包;如果包名称后面跟有三个点,代表这个包及其子包;如果只有三个点,代表无名包。关闭assertion功能参数为-da,使用方法与-ea类似。

  -ea-da的全名为-enableassertions-disenableassertions,全名和缩写名有同样的功能。

  下面表格表示了参数及其含义,并有例子说明如何使用。

  参数 例子 说明

  -ea java -ea 打开所有用户类的assertion

  -da java -da 关闭所有用户类的assertion

  -ea: java -ea:MyClass1 打开MyClass1assertion

  -da: java -da: MyClass1 关闭MyClass1assertion

  -ea: java -ea:pkg1 打开pkg1包的assertion

  -da: java -da:pkg1 关闭pkg1包的assertion

  -ea:... java -ea:... 打开缺省包(无名包)assertion

  -da:... java -da:... 关闭缺省包(无名包)assertion

  -ea:... java -ea:pkg1... 打开pkg1包和其子包的assertion

  -da:... java -da:pkg1... 关闭pkg1包和其子包的assertion

  -esa java -esa 打开系统类的assertion

  -dsa java -dsa 关闭系统类的assertion

      1.6)说明

       assertion为开发人员提供了一种灵活地调试和测试机制,它的使用也非常简单、方便。


   
设置执行参数:
   
 

 

   
即可。 
  

 

断言概述


  
编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设
  
可以将断言看作是异常处理的一种高级形式
  
断言表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真
  
可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言而在部署时禁用断言。同样,程序投入运行后,最终用户在遇到问题时可以重新起用断言。
  
使用断言可以创建更稳定,品质更好且易于除错的代码
  
当需要在一个值为FALSE时中断当前操作的话,可以使用断言
  
单元测试必须使用断言(Junit/JunitX
  
除了类型检查和单元测试外,断言还提供了一种确定个种特性是否在程序中得到维护的极好的方法
  
使用断言使我们向按契约式设计更近了一部


常见的断言特性


  
前置条件断言:代码执行之前必须具备的特性
  
后置条件断言:代码执行之后必须具备的特性
  
前后不变断言:代码执行前后不能变化的特性


断言使用方式


  
断言可以有两种形式
  1.assert Expression1
  2.assert Expression1:Expression2
  
其中Expression1应该总是一个布尔值,Expression2是断言失败时输出的失败消息的字符串。如果Expression1为假,则抛出一个 AssertionError,这是一个错误,而不是一个异常,也就是说是一个不可控制异常(unchecked Exception),AssertionError由于是错误,所以可以不捕获,但不推荐这样做,因为那样会使你的系统进入不稳定状态。


起用断言


  
断言在默认情况下是关闭的,要在编译时启用断言,需要使用source1.4标记 javac source1.4 Test.java ,在运行时启用断言需要使用 -ea参数 。要在系统类中启用和禁用断言可以使用 -esa  -dsa参数。
  
例如:
public class AssertExampleOne{
   public AssertExampleOne(){}
   public static void main(String args[]){
      int x=10;
      System.out.println("Testing Assertion that x==100");
      assert x==100:"Out assertion failed!";
      System.out.println("Test passed!");
   }
}

如果编译时未加 -source1.4,则编译通不过
在执行时未加 -ea 时输出为
Testing Assertion that x==100
Test passed
jre
忽略了断言的就代码,而使用了该参数就会输出为
Testing Assertion that x==100
Exception in thread "main" java.lang.AssertionError: Out assertion failed!
        at AssertExampleOne.main(AssertExampleOne.java:6)


断言的副作用


  
由于程序员的问题,断言的使用可能会带来副作用 ,例如:
  boolean isEnable=false;
  //...
  assert isEnable=true;
  
这个断言的副作用是因为它修改了程序中变量的值并且未抛出错误,这样的错误如果不细心的检查是很难发现的。但是同时我们可以根据以上的副作用得到一个有用的特性,根据它来测试断言是否打开。

 public class AssertExampleTwo{

   public static void main(String args[]){
     boolean isEnable=false;
     //...
     assert isEnable=true;
     if(isEnable==false){
       throw new RuntimeException("Assertion shoule be enable!");
     }
   }
}


何时需要使用断言


  1.
可以在预计正常情况下程序不会到达的地方放置断言 assert false
  2.
断言可以用于检查传递给私有方法的参数。(对于公有方法,因为是提供给外部的接口,所以必须在方法中有相应的参数检验才能保证代码的健壮性)
  3.
使用断言测试方法执行的前置条件和后置条件
  4.
使用断言检查类的不变状态,确保任何情况下,某个变量的状态必须满足。(如age属性应大于0小于某个合适值)


什么地方不要使用断言


  
断言语句不是永远会执行,可以屏蔽也可以启用
因此:
  1.
不要使用断言作为公共方法的参数检查,公共方法的参数永远都要执行

(很多文章都是这么说的,但是不是很明白,看了下官方文档)

Do not use assertions for argument checking in public methods.

Argument checking is typically part of the published specifications (or contract) of a method, and these specifications must be obeyed whether assertions are enabled or disabled. Another problem with using assertions for argument checking is that erroneous arguments should result in an appropriate runtime exception (such as IllegalArgumentException, IndexOutOfBoundsException, or NullPointerException). An assertion failure will not throw an appropriate exception.

也就是就是公共方法它的参数检测不应该和assertions启用和关闭有关。如果你的测试失败了,assertions所抛出的异常其实不是一个真正你参数测试失败的异常!
  2.
断言语句不可以有任何边界效应,不要使用断言语句去修改变量和改变方法的返回值

参考:
http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html

 

  • 大小: 13.7 KB
分享到:
评论

相关推荐

    Java陷阱之assert关键字

     在Java中,assert关键字是从JAVA SE 1.4 引入的,为了避免和老版本的Java代码中使用了assert关键字导致错误,Java在执行的时候默认是不启动断言检查的(这个时候,所有的断言语句都将忽略!),如果要开启断言...

    Java陷阱之assert关键字详解

    详细介绍了Java陷阱之assert关键字,有需要的朋友可以参考一下

    java2参考大全 中文

    本书由世界级编程大师Herbert Schildt撰写,英文原书一经出版,就受到了读者的热烈欢迎。...书中包含了Java 2, 版本1.3中新增的特征,其中最重要的是assert关键字、基于通道的I/O子系统、成链的异常和网络增强功能等。

    java 常用英语词汇大全

    java 常用英语词汇大全 部分内容如下: algorithm n.算法['.lg.riem] annotation [java]代码注释[.n.u'tei..n] anonymous adj....(反义:directly adv....assert (关键字) 断言[.'s.:t] ‘ (java 1.4 之后成为关键字

    JAVA--达内培训笔记

    java中没有sizeof这个关键字了,java中的boolean类型的值只能用true和false,且这两个也是关键字 enum 枚举 assert 断言 一个标识符尽量符合语义信息,提高程序可读性 类 名 :每个单词首字母大写, 变量和...

    JavaSE_2_异常处理

    异常的处理流程,异常类的继承关系,异常的统一出口,throws关键字,throw关键字,异常的标准处理结构,RuntimeException与Exception的区别,自定义异常类,assert关键字,Eclipse debug

    JAVA面试题最全集

    给定一个C语言函数,要求实现在java类中进行调用。 45.如何获得数组的长度? 46.访问修饰符“public/private/protected/缺省的修饰符”的使用 47.用关键字final修饰一个类或者方法时,有何意义? 48.掌握类和...

    java面试宝典

    46、java 中实现多态的机制是什么? 12 47、在java 中一个类被声明为final 类型,表示了什么意思? 12 48、下面哪些类可以被继承? 12 49、指出下面程序的运行结果: 【基础】 13 52、关于内部类: 13 53、数据类型...

    java 面试题 总结

    声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其...

    Java面试宝典-经典

    23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? 17 25、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized? 18 26、什么是内部类?Static Nested ...

    Java面试宝典2010版

    23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? 17 25、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized? 18 26、什么是内部类?Static Nested ...

    java面试题大全(2012版)

    23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? 17 25、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized? 18 26、什么是内部类?Static Nested ...

    java面试题

    62. java中实现多态的机制是什么? 42 63. 垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收? 42 63.1. 判断该对象是否是时候可以收集方法 43 63.1.1. 引用计数 ...

    java面试宝典2012版.pdf

    23、java中实现多态的机制是什么? 24、abstract class和interface有什么区别? 25、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized? 26、什么是内部类?Static Nested Class ...

    Java JDK 7学习笔记(国内第一本Java 7,前期版本累计销量5万册)

    必须要时从Java SE API的源代码分析,了解各种语法在Java SE API中如何应用。  《Java JDK 7学习笔记》将IDE操作纳为教学内容之一,使读者能与实践结合,提供的视频教学能更清楚地帮助读者掌握操作步骤。 内容简介 ...

    最新Java面试宝典pdf版

    23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? 17 25、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized? 18 26、什么是内部类?Static Nested ...

    整理后java开发全套达内学习笔记(含练习)

    assert (关键字) 断言 [ә'sә:t] ' (java 1.4 之后成为关键字) associate n.关联(同伴,伙伴) [ә'sәuʃieit] attribute n.属性(品质,特征) [ә'tribju:t] boolean (关键字) 逻辑的, 布尔型 call n.v.调用; 呼叫...

    java基础题 很全面

    57. java中实现多态的机制是什么? 14 58. 垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收? 14 59. 静态变量和实例变量的区别? 14 60. 什么是java序列化,如何实现...

Global site tag (gtag.js) - Google Analytics