java中的assert关键字及⽤法:java中的可以抛出的错误(Error)和异常(Exception)都是 java.lang.Throwable的⼦类。
Throwable 类的⼦类有两类: Error 和 Exception。 下⾯要⽤到的AssertionError 是 Error类的⼦类。使⽤了assert 的java 源⽂件: TestAssert.java
package cn.wzb;
public class TestAssert {
public TestAssert() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
TestAssert test = new TestAssert();
try {
//assert false:"TestErrorMessage!"; // to trigger an AssertionError when using java -ea option
assert false:"TestErrorMessage!";
}catch(AssertionError ae) {
System.out.println("There is an AssertionError here, please check!");
System.out.println("The Error Message is : " + ae.getMessage());
ae.printStackTrace();
}catch(Throwable t){
System.out.println("There is an unknown Error is thrown here");
t.printStackTrace();
}
}
public void myAssert(boolean b) {
assert b ? true : false;
System.out.println("This is the true conditions !");
}
}
package cn.wzb;
public class TestAssert {
public TestAssert() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
TestAssert test = new TestAssert();
try {
assert false:"TestErrorMessage!"; // to trigger an AssertionError when using java -ea option
}catch(AssertionError ae) {
System.out.println("There is an AssertionError here, please check!");
System.out.println("The Error Message is : " + ae.getMessage());
ae.printStackTrace();
}catch(Error e){
System.out.println("the Error is : " + e.getMessage());
e.printStackTrace();
}catch(Throwable t){
System.out.println("There is an unknown Error is thrown here");
t.printStackTrace();
}
}
public void myAssert(boolean b) {
assert b ? true : false;
System.out.println("This is the true conditions !");
}
}
默认的情况下, assert 关键字是不起作⽤,需开启虚拟机选 -ea , enable assertion. 开启jvm的断⾔选项。
1. 命令⾏编译的⽅法:
在源⽂件所在的⽬录,执⾏:
其中 -d ⽤来指定⽣成class及其包的⽬录, . 表⽰当前⽬录。
2. 命令⾏测试的⽅法:
在包所在的⽬录中,执⾏:
说明:必须加包名在class前,否则,会报ClassNotFoundException 。
在eclipse 中编译: 打开ae选项: Run -》 Run Configurations -》Arguments -》Vm arguments : -ae.
关于assert 补充:
有这样⼀个观点:"在测试时使⽤断⾔,⽽在产品发布时将断⾔关闭的程序员,就像是在岸上操练时穿着救⽣⾐,⽽下海时将救⽣⾐脱掉的⽔⼿。" 在java⽣产系统中,很少看到断⾔的存在,即使在⽤Junit测试,多数情况下也是System.out.println来获取结果,断⾔被束之⾼阁。存在即合理,jdk(1.4以后的版本)既然把assert作为他的关键字,肯定是系统应⽤中有相关的场景。
java中的assert的语法:assert booleanvalue : error info。如果是返回false,则抛出java.lang.AssertionError,这个类继承了Error类(Error 是 Throwable 的⼦类,⽤于指⽰合理的应⽤程序不应该试图捕获的严重问题),所以系统抛出这类异常的时候,你可以不处理(这不代表你不能catch)。⽣产系统的多数异常都是需要处理并返回给⽤户,所以我们可以在系统设计的核⼼业务调⽤的位置catch AssertionError错误。
public void assertor(){
int x =1;
assert x==1?true:false;
System.out.println("print yes");
assert x==2?true:false : "有错误!";
System.out.println("no print");
}
在eclipse执⾏这段代码,可以正常的执⾏完毕,并没有发现问题。这是因为eclipse默认是关闭断⾔的,通过添加参数 -ea 来打开断⾔,就发现有以下错误:
java.lang.AssertionError: 有错误!
在代码中添加捕获异常的代码,然后可以做相关的处理。
public void assertor(){
int x =1;
assert x==1?true:false;
System.out.println("print yes");
try {
assert x==2?true:false : "有错误!";
} catch (AssertionError e) {
System.out.println("has error");
}
System.out.println("no print");
}
在web service系统API中,请求过程中会有很多的参数校验,多数参数需要判断参数是否为空,程序中会有这样的代码:
if(StringUtils.isBlank("name")){
//doing someting
}
if(StringUtils.isBlank("age")){
//doing someting
}
或者是重构⼀把,把参数放⼊map中,统⼀的去遍历map来解决这个问题。
Map<String,String> map = new HashMap<String, String>();
map.put("name",name);
//通过map来遍历处理抛出错误来校验。
public void VolicateNull(Map<String,String> map){
for(Entry<String,String> Set()){
if(StringUtils.Value())){
throw new Key());
}
}
}
在我们new 对象的时候创建了系统资源,虽然jdk可以⾃动回收,但是也造成了相关的系统浪费,因为assert可以帮你完成相关操作的。我们可以在系统中这样:
assert StringUtils.isBlank("name") : "some message";
assert StringUtils.isBlank("age") : "some message";
⽽后捕获错误,做出相关的处理。
也许你觉得JDK中的异常⽤的不爽,这些都是Error的东东,看着觉得头痛,那你可以常识⽤Sprint中的org.springframework.util.Assert类来做相关的处理,这个类抛出IllegalArgumentException异常,做
参数的校验再好也不过了。⾥⾯的⽅法很全,可以看源码了解,例如为空的判断。
public static void isNull(Object object, String message) {
if (object != null) {
throw new IllegalArgumentException(message);
}
}
补充2:
⼀、assertion的意义和⽤法
J2SE 1.4在语⾔上提供了⼀个新特性,就是assertion功能,它是该版本在Java语⾔⽅⾯最⼤的⾰新。
从理论上来说,通过 assertion⽅式可以证明程序的正确性,但是这是⼀项相当复杂的⼯作,⽬前还没有太多的实践意义。
在实现中,assertion就是在程序中的⼀条语句,它对⼀个boolean表达式进⾏检查,⼀个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。
⼀般来说,assertion⽤于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提⾼性能,在软件发布后,assertion检查通常是关闭的。
1、语法表⽰
在语法上,为了⽀持assertion,Java增加了⼀个关键字assert。它包括两种表达式,分别如下:
assert expression1;
assert expression1:expression2;
在两种表达式中,expression1表⽰⼀个boolean表达式, expression2表⽰⼀个基本类型或者是⼀个对象(Object),基本类型包括
boolean,char,double,float,int和 long。由于所有类都为Object的⼦类,因此这个参数可以⽤于所有对象。
2、含义isnull的用法
在运⾏时,如果关闭了assertion功能,这些语句将不起任何作⽤。如果打开了assertion功能,那么expression1的值将被计算,如果它的值为false,该语句强抛出⼀个AssertionError对象。
如果assertion语句包括expression2参数,程序将计算出 expression2的结果,然后将这个结果作为AssertionError的构造函数的参数,来创建AssertionError对象,并抛出该对象;如果expression1值为true,expression2将不被计算。
⼀种特殊情况是,如果在计算表达式时,表达式本⾝抛出Exception,那么assert将停⽌运⾏,⽽抛出这个Exception。
3、编译
由于assert是⼀个新关键字,使⽤⽼版本的JDK是⽆法编译带有assert的源程序。因此,我们必须使⽤JDK1.4(或者更新)的Java编译器,在使⽤Javac命令时,我们必须加上-source 1.4作为参数。-source 1.4表⽰使⽤JDK 1.4版本的⽅式来编译源代码,否则编译就不能通过,因为缺省的Javac编译器使⽤JDK1.3的
语法规则。
⼤家在使⽤eclipse,jbuilder等IDE⼯具的时候,要注意编译器的版本,使⽤的jre,不等于是javac 的版本
⼀个简单的例⼦如下: javac -source 1.4 AssertTest.java
4、运⾏
由于我们可以选择开启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 - 打开pkg1包和其⼦包的assertion
-da:... java - 关闭pkg1包和其⼦包的assertion
-esa java -esa 打开系统类的assertion
-dsa java -dsa 关闭系统类的assertion
综合使⽤ java -dsa:MyClass1:pkg1 关闭MyClass1和pkg1包的assertion
其中...代表,此包和其⼦包的含义。例如我们有两个包为pkg1和pkg1.subpkg。
那么就代表pkg1和pkg1.subpkg两个包。
另外,Java为了让程序也能够动态开启和关闭某些类和包的assertion功能,Java修该了Class和ClassLoader的实现,增加了⼏个⽤于操作assert的API。下⾯简单说明⼀下⼏个API的作⽤。
ClassLoader类中的⼏个相关的API:
setDefaultAssertionStatus:
⽤于开启/关闭assertion功能
setPackageAssertionStatus:
⽤于开启/关闭某些包的assertion功能
setClassAssertionStatus:
⽤于开启/关闭某些类的assertion功能
clearAssertionStatus:
⽤于关闭assertion功能
⼆、assertion的设计问题
⾸先,我们认为assertion是必要的。因为,如果没有统⼀的assertion机制,Java程序通常使⽤if-then-else或者switch-case语句进⾏assertion检查,⽽且检查的数据类型也不完全相同。
assertion机制让Java程序员⽤统⼀的⽅式处理assertion问题,⽽不是按⾃⼰的⽅式处理。另外,如果⽤户使⽤⾃⼰的⽅式进⾏检查,那么这些代码在发布以后仍然将起作⽤,这可能会影响程序的性能。⽽从语⾔⾔层次⽀持 assertion功能,这将把assertion对性能带来的负⾯影响降到最⼩。
Java是通过增强⼀个关键字assert实现⽀持assertion,⽽不是使⽤⼀个库函数⽀持,这说明Java认为assertion对于语⾔本⾝来说是⾮常重要的。C语⾔就是通过Assert.h函数库实现断⾔的⽀持。
Java的assertion的开启也和C语⾔不太⼀样,我们都知道在C语⾔中,assertion的开启是在编译时候决定的。当我们使⽤debug⽅式编译程序时
候,assertion被开启,⽽使⽤release⽅式编译时候,assertion⾃动被关闭。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论