J2SE 1.4在语言上提供了一个新特性,就是assertion(断言)功能,它是该版本在Java语言方面最大的革新。在软件开发中,assertion是一种经典的调试、测试方式。
assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制,如C,C++和Eiffel等,但是支持的形式不尽相同,有的是通过语言本身、有的是通过库函数等。另外,从理论上来说,通过assertion方式可以证明程序的正确性,但是这是一项相当复杂的工作,目前还没有太多的实践意义。
在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后,assertion检查通常是关闭的。下面简单介绍一下Java中assertion的实现。
1.1) 语法表示
在语法上,为了支持assertion,Java增加了一个关键字assert。它包括两种表达式,分别如下:
assert expression1;
assert expression1: expression2;
在两种表达式中,expression1表示一个boolean表达式,expression2表示一个基本类型或者是一个对象(Object) ,基本类型包括boolean,char,double,float,int和long。由于所有类都为Object的子类,因此这个参数可以用于所有对象。
1、assert
如果为true,则程序继续执行。
如果为false,则程序抛出AssertionError,并终止执行。
2、assert : <错误信息表达式>
如果为true,则程序继续执行。
如果为false,则程序抛出java.lang.AssertionError,并输出<错误信息表达式>。
1.2) 语义含义
在运行时,如果关闭了assertion功能,这些语句将不起任何作用。如果打开了assertion功能,那么expression1的值将被计算,如果它的值为false,该语句强抛出一个AssertionError对象。如果assertion语句包括expression2参数,程序将计算出expression2的结果,然后将这个结果作为AssertionError的构造函数的参数,来创建AssertionError对象,并抛出该对象;如果expression1值为true,expression2将不被计算。
一种特殊情况是,如果在计算表达式时,表达式本身抛出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语句的程序运行时,使用了新的ClassLoader和Class类,因此,这种程序必须在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 打开MyClass1的assertion
-da: java -da: MyClass1 关闭MyClass1的assertion
-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
相关推荐
在Java中,assert关键字是从JAVA SE 1.4 引入的,为了避免和老版本的Java代码中使用了assert关键字导致错误,Java在执行的时候默认是不启动断言检查的(这个时候,所有的断言语句都将忽略!),如果要开启断言...
### Java中的关键字大全 在Java编程语言中,关键字是一组预定义的词汇,它们具有特殊的含义和用途。理解和掌握这些关键字对于编写有效的Java程序至关重要。本文将详细介绍Java中的一些核心关键字,并提供相应的解释...
标题中提到的“Java陷阱之assert关键字详解”所指的知识点主要涉及Java语言中assert关键字的介绍、使用、限制以及使用时需注意的潜在问题。Assert关键字作为Java SE 1.4版本引入的功能,其设计目的是为了帮助开发者...
在编程语言的学习中,了解和掌握关键字是至...同时,随着Java版本的更新,也可能出现新的关键字,例如`assert`用于断言,`enum`用于枚举类型等。不断学习和掌握新的关键字,有助于提升我们的编程技能和解决问题的能力。
在Java语言中,关键字是具有特殊意义的保留字,它们不能用作变量名、方法名或类名等标识符。Java的关键字用于定义程序结构的重要组成部分,如控制语句、数据类型等。 - **常见关键字**: - `if`, `else`, `while`,...
Java 共有 50 多个关键字,它们包括但不限于 `abstract`、`assert`、`boolean`、`break`、`byte`、`case`、`catch`、`char`、`class`、`const`(虽然未使用)、`continue`、`default`、`do`、`double`、`else`、`...
Java拥有51个关键字,这些关键字在编程中扮演着核心角色,用于声明类型、控制流程、异常处理等。下面我们将逐一介绍这些关键字: 1. **abstract**:用于定义抽象类和抽象方法,表示该类不能被实例化,或方法没有...
Java编程语言中有51个关键字,它们在程序中扮演着至关重要的角色,用来定义类、接口、变量、方法以及控制程序流程。以下是一些主要的关键字及其解释: 1. `abstract`:抽象关键字,用于声明抽象类和抽象方法。抽象...
Java编程语言中包含了一系列的关键字和保留字,这些词汇具有特殊的含义,用于构建程序结构和控制程序流程。关键字是Java语言预定义的标识符,它们在编译器中有特殊的解释,不能作为变量、函数名或其他标识符使用。...
本文将详细介绍Java中的关键字及其用途。 #### 关键字列表与解释 1. **abstract** - **用途**:用于声明抽象类和抽象方法。抽象类不能实例化,只能作为其他类的父类。抽象方法是没有实现的方法,必须在子类中提供...
2. assert: 用于在代码中进行调试断言,但在Java中被禁用。 3. boolean: 基本数据类型,用于表示逻辑值true或false。 4. break: 用于立即退出循环或switch语句。 5. byte: 基本数据类型,表示8位的有符号整数。 6. ...
Java的关键字,即保留字,是Java语言中具有特殊意义的标识符,它们预定义并保留用于语言本身的语法结构。理解这些关键字是学习Java的基础之一。本文将详细介绍Java中的50个常用关键字,并按照其功能类别进行分类。 ...
JAVA关键字列表 Java是一种面向对象的编程语言,具有多种关键字,用于控制程序的执行、定义变量、类和方法等。本文档系统列举了Java的关键字及其用法分类,总共分为以下几个类别:访问控制、类、变量修饰符、流程...
在Java中,一共有51个关键字(包括保留字),但描述中提到的是48个,可能是因为某些关键字在特定上下文不常用或者被归类到保留字中。下面将详细介绍这些关键字及其用途。 1. **abstract** - 用于声明抽象类或抽象...
在Java编程语言中,关键字是具有特殊含义的预定义标识符,它们被Java解析器用来识别语法结构。这些关键字不能用作变量名、类名或方法名。在Java中,一共有53个关键字,包括两个保留字。下面将详细阐述这些关键字的...
10. **const**:预留关键字,但在Java中未使用。 11. **continue**:跳过当前循环体剩余的部分,进入下一次循环。 12. **default**:在switch语句中,没有匹配到case时执行的代码块。 13. **do**:与while一起...
Java的关键字包括但不限于`abstract`, `assert`, `boolean`, `break`, `byte`, `case`, `catch`, `char`, `class`, `const`, `continue`, `default`, `do`, `double`, `else`, `enum`, `extends`, `final`, `finally...
虽然在早期的Java版本中存在`const`关键字,但它并未被使用,并且在Java 1.5之后已经被废弃。 #### 11. `continue` `continue`关键字用于跳过当前循环中的剩余部分,并继续下一次迭代。 **示例:** ```java for ...
在Java编程语言中,关键字是具有特殊含义的保留词汇,它们是编程语法的重要组成部分,用于定义程序结构和控制流程。了解这些关键字的含义对于编写有效的Java代码至关重要。下面,我们将详细探讨Java中的所有关键字...
Java的关键字主要包括`abstract`, `assert`, `boolean`, `break`, `byte`, `case`, `catch`, `char`, `class`, `const`, `continue`, `default`, `do`, `double`, `else`, `enum`, `extends`, `final`, `finally`, `...