——Java培训、Android培训、iOS培训、.Net培训 期待与您共同交流!——
异常处理
在JAVA语言出现以前,传统的异常处理方式多采用返回值来标识程序出现的异常情况,这种方式虽然为程序员所熟悉,但却有多个坏处。
首先,一个API可以返回任意的返回值,而这些返回值本身并不能解释该返回值是否代表一个异常情况发生了和该异常的具体情况,需要调用API的程序自己判断并解释返回值的含义。
其次,并没有一种机制来保证异常情况一定会得到处理,调用程序可以简单的忽略该返回值,需要调用API的程序员记住去检测返回值并处理异常情况。这种方式还让程序代码变得冗长,尤其是当进行IO操作等容易出现异常情况的处理时,代码的很大部分用于处理异常情况的switch分支,程序代码的可读性变得很差。
当程序中抛出一个异常后,程序从程序中导致异常的代码处跳出,java虚拟机检测寻找和try关键字匹配的处理该异常的catch块,如果找到,将控制权交到catch块中的代码,然后继续往下执行程序,try块中发生异常的代码不会被重新执行。如果没有找到处理该异常的catch块,在所有的finally块代码被执行和当前线程的所属的ThreadGroup的uncaughtException方法被调用后,遇到异常的当前线程被中止。
Java异常结构中定义有Throwable类,Exceotion和Error是其派生的两个子类。其中Exception表示由于网络故障、文件损坏、设备错误、用户输入非法等情况导致的异常,这类异常是可以通过Java异常捕获机制处理的。而Error表示Java运行时环境出现的错误,例如:JVM内存溢出等。
try {…} 语句指定了一段代码,该段代码就是一次捕获并处理例外的范围。在执行过程中,该段代码可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句分别对这些异常做相应的处理。
如果没有列外产生,所有的catch代码段都被略过不执行
在catch语句块中是对异常进行处理的代码。catch中声明的异常对( catch(SomeException e) )封装了异常事件发生的信息,在catch语句块中可以使用这个对象的一些方法获取这些信息
常见格式:
...
try{
//可能出现异常的代码片段
}catch(Exception e){
//处理该异常的代码片段
}
...
每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常 。catch捕获的异常类型由上至下的捕获异常类型的顺序应是子类到父类的
例如
try{
…
}catch(NullPointerException e){//子类异常应在上面捕获
…
}catch(RuntimeException e){//父类异常在下面捕获
…
}catch(Exception e){//应养成最终捕获Exception的习惯
…
}
通常在书写代码的时候,我们应当在最后一个catch中捕获Exception,这样可以保证代码不会因为出现一个未在catch中声明的异常而导致捕获失败使得程序终止。
finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序其它部分以前,能够对程序的状态作统一管理。
无论try所指定的程序块中是否抛出例外,finally所指定的代码都要被执行,通常在finally语句中可以进行资源的消除工作,如关闭打开的文件、删除临时文件等。
finally语句块只能定义在try语句块之后,或者最后一个catch语句块之后,且只能定义一次。
当程序发生错误而无法处理的时候,会抛出对应的异常对象,除此之外,在某些时刻,您可能会想要自行抛出异常,例如在异常处理结束后,再将异常抛出,让下一层异常处理区块来捕捉,若想要自行抛出异常,您可以使用“throw”关键词,并生成指定的异常对象。
例如:
thrownewArithmeticException();
程序中会声明许多方法(Method),这些方法中可能会因某些错误而引发异常,但您不希望直接在这个方法中处理这些异常,而希望调用这个它的方法来统一处理,这时候您可以使用“throws”关键词来声明这个方法将会抛出异常
例如:
publicstatic void stringToDate(String str)throws ParseException{ ……
}
当使用继承时,在父类的某个方法上声明了throws抛出某些异常,而在子类中重些该方法时,我们可以做以下的操作:
不处理异常(重写方法时不声明throws)
可仅在throws中声明父类中声明的部分异常
可在throws中声明父类方法中抛出的异常的子类异常
但是不能做以下操作:
重写方法时在throws中出声明抛出额外的异常
重写方法是在throws中声明父类方法中声明的抛出异常的父类异常
Java异常可以分为可检测异常,非检测异常
可检测异常:可检测异常经编译器验证,对于声明抛出异常的任何方法,编译器将强制执行处理或声明规则,不捕捉这个异常,编译器就通不过,不允许编译
非检测异常:非检测异常不遵循处理或者声明规则。在产生此类异常时,不一定非要采取任何适当操作,编译器不会检查是否已经解决了这样一个异常
RuntimeException 类属于非检测异常,因为普通JVM操作引起的运行时异常随时可能发生,此类异常一般是由特定操作引发。但这些操作在java应用程序中会频繁出现。因此它们不受编译器检查与处理或声明规则的限制 。
IllegalArgumentException
抛出的异常表明向方法传递了一个不合法或不正确的参数
NullPointerException
当应用程序试图在需要对象的地方使用 null 时,抛出该异常
ArrayIndexOutOfBoundsException
当使用的数组下标超出数组允许范围时,抛出该异常
ClassCastException
当试图将对象强制转换为不是实例的子类时,抛出该异常
NumberFormatException
当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
Throwable中定义了一个方法可以输出错误信息,用来跟踪异常事件发生时执行堆栈的内容。该方法定义为:
void printStackTrace()
例如:
try{
…
}catch(Exception e){
e.printStackTrace();//输出执行堆栈信息
}
Throwable中定义了一个方法可以得到有关异常事件的信息。该方法定义为:
StringgetMessage()
例如:
try{
…
}catch(Exception e){
System.out.println(e.getMessage());
}
很多时候,当一个异常由另一个异常导致异常而被抛出的时候,Java库和开放源代码会将一种异常包装成另一种异常。这时,日志记录和打印根异常就变得非常重要。Java异常类提供了 getCause()方法来检索导致异常的原因,这些可以对异常根层次的原因提供更多的信息。该Java实践对代码的调试或故障排除有很大的帮助。另外,如果要把一个异常包装成另一种异常,构造一个新异常就要传递源异常。
Throwable getCause()
获取该异常出现的原因
Java异常机制可以保证程序更安全和更健壮。虽然Java类库已经提供很多可以直接处理异常的类,但是有时候为了更加精准地捕获和处理异常以呈现更好的用户体验,需要开发者自定义异常。
创建自定义异常类,语法格式:
publicclass[自定义异常类名]extends Exception{
…
}
当定义好自定义异常后,我们可以通过Eclipse来自动生成相应的构造方法。
具体步骤如下:
①声明一个类并继承自Exception
②右键点击点击Source
③选择Generate Constructors from Superclass
④选中父类中所有构造方法后确认生成
例如:
publicclass MyException extends Exception{
publicMyException(){
super();
// TODO Auto-generated constructor stub
}
publicMyException(String message, Throwable cause){
super(message, cause);
// TODO Auto-generated constructor stub
}
publicMyException(String message){
super(message);
// TODO Auto-generated constructor stub
}
publicMyException(Throwable cause){
super(cause);
// TODO Auto-generated constructor stub
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u010111458/article/details/47167317