对Java来说,异常就是一个类,产生了一个异常,就是产生了一个Exception类的对象,这个类代表不正常的现象。
1. 异常的继承体系
在Java中使用Exception类来描述异常。它的父类是Throwable。Throwable是Java 语言中所有错误或异常的super类。
我们再来观察Throwable类,能够发现与Exception类平级的有一个Error类。Error也是Throwable的子类,它用来表示java程序中可能会产生的严重错误。解决办法只有一个,修改代码避免Error错误的产生。
Throwable(生病)Error (不可治愈的疾病) :宕机,断点,海啸Exception (能治愈的疾病) : 异常,程序员能处理非RuntimeExcetion 非运行时期异常,编译器异常,要求我们在编译器就必须进行处理RuntimeException(运行时期异常 )
2. 异常产生的后果
- 如果对发生的异常不处理,异常会被抛出给调用函数。如果对发生的异常一直不处理,则代码停止执行,并且将异常直接抛给JVM。
如果对发生的异常进行
try-catch,try下的代码不会执行,此异常会被catch捕获,同时程序继续执行3. 异常的处理
A. throw and throws
在java中,提供了一个
throw关键字,它用来抛出一个指定的异常对象:throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过
throws在定义方法时声明所有可能被抛出的异常,让调用者去处理。public static int getElement(int[] arr,int index) throws NullPointerException, ArrayIndexOutOfBoundsException { if(arr==null){ throw new NullPointerException("arr指向的数组不存在"); } if(index<0 || index>=arr.length){ throw new ArrayIndexOutOfBoundsException("错误的角标,"+index+"索引在数组中不存在"); } int element = arr[index]; return element; }B. try-catch-finally
try{ // 可能发生异常的代码 }catch(异常类型 e1| 异常类型 e2){ //如果产生异常,进行的处理 e.printStackTrace() 打印 针对于程序员的 }catch(异常类型 e3) { throw e3; } finally { //无论程序是否有异常出现, finally中的代码必须执行。一般用于释放资源 }注意:
e1 和 e2 必须是同级异常
- e3 必须是 e1 和 e2的同级或者父类如
RuntimeException或Exception finally返回路径:如果return发生在try块或者catch块中,每次碰到return就会在返回路径中临时存储这个被返回的值。无论finally方法内有任何的改变,返回路径中的这个值一致不变。C. 异常的分类
异常分为编译异常和运行异常:
编译异常(Exception 及其直接子类): 在Java中, Exception类中除了 RuntimeException类及其子类都是编译时异常。编译时异常的特点是Java编译器会对其进行检查,如果出现异常就必须对异常进行处理,否则程序无法通过编译。
处理编译时期的异常有两种方式,具体如下:
(1)使用try…catch语句对异常进行捕获。
(2)使用throws关键字声明抛出异常,调用者对其处理。
运行异常(RuntimeException): RuntimeException类及其子类都是运行时异常。运行时异常的特点是Java编译器不会对其进行检查,也就是说,当程序中出现这类异常时,即使没有使用try…catch语句捕获或使用throws关键字声明抛出,程序也能编译通过。运行时异常一般是由程序中的逻辑错误引起的,在程序运行时无法恢复。比如通过数组下标访问越界,除以0.
4. 方法重写时,throws规则
父类的方法如果有异常抛出,子类重写后可以不抛出异常。
父类的方法如果有异常抛出,子类重写后有异常抛出,抛出的异常不能大于(继承关系)父类异常。
父类的方法如果没有异常抛出,子类重写后不能抛出异常。只能通过try-catch块对异常进行处理。5. 获取异常详情:
Throwable类中的三个方法都和异常的信息有关系:String getMessage() 获取message属性的值 异常了!
- String toString() 对异常信息的描述 java.lang.Exception: 异常了!
void printStackTrace() 将异常信息追踪到标准的错误流.异常信息最全,JVM默认调用方法也是这个方法.
public class ExceptionDemo1 { public static void main(String[] args) { try{ function(); }catch(Exception ex){ //System.out.println(ex.toString()); ex.printStackTrace(); } } public static void function() throws Exception{ throw new Exception("异常了!"); } }6. 自定义异常
在一个大型项目中,可以自定义新的异常类型,但是,保持一个合理的异常继承体系是非常重要的。
一个常见的做法是自定义一个BaseException作为“根异常”,然后,派生出各种业务类型的异常。BaseException需要从一个适合的Exception派生,通常建议从RuntimeException派生:public class BaseException extends RuntimeException { }其他业务类型的异常就可以从
BaseException派生:public class UserNotFoundException extends BaseException { } public class LoginFailedException extends BaseException { }自定义的
BaseException应该提供多个构造方法:public class BaseException extends RuntimeException { public BaseException() { super(); } public BaseException(String message, Throwable cause) { super(message, cause); } public BaseException(String message) { super(message); } public BaseException(Throwable cause) { super(cause); } }述构造方法实际上都是原样照抄
RuntimeException。这样,抛出异常的时候,就可以选择合适的构造方法。通过IDE可以根据父类快速生成子类的构造方法。
