异常处理机制
Java语言按照面向对象的思想来处理异常:
- 把各种不同类型的异常情况进行分类,用Java类来表示异常情况,这种类被称为异常类。
public class CarWrongException extends Exception{/** 表示车子出故障的异常情况 */}
- 用throws语句在方法声明处声明抛出特定异常,用throw语句在方法中抛出具体的异常
- 用try-catch语句来捕获并处理异常。
处理异常的两种办法
如果方法中的代码块可能抛出异常,有两种处理办法:
(1)在当前方法中通过try-catch语句捕获并处理异常,例如:
public void methodA(int money){
try{
//以下代码可能会抛出SpecialException
if(--money<=0) throw new SpecialException("Out of money");
}catch(SpecialException e){
处理异常
}
}
(2)在方法的声明处通过throws语句声明抛出异常,例如:
public void methodA(int money) throws SpecialException{
//以下代码可能会抛出SpecialException
if(--money<=0) throw new SpecialException("Out of money");
异常处理流程
main函数调用method(B),method(B)调用method(A),因为method(A)中有异常,method(B)要调用就必须处理异常,若method(B)也只是抛出异常就类推给main函数处理;
public class MainCatcher{
public void methodA(int money)throws SpecialException{
if(--money<=0) throw new SpecialException("Out of money"); //表达式满足条件,所以抛出了异常
System.out.println("methodA"); //上述表达式满足条件,所以不打印这句话,直接跳到method(B)
}
public void methodB(int money) throws SpecialException{
methodA(money); //method(B)也只是抛出了异常,并未处理异常,所以不打印语句,直接回到main函数
System.out.println("methodB");
}
public static void main(String args[]){
try{
new MainCatcher().methodB(1);
System.out.println("main"); //因为method(B)有异常
}catch(SpecialException e){
System.out.println("Wrong"); //异常的处理
}
}
}
该程序的打印结果为:Wrong。
如果把main()方法中的methodB(1)改为methodB(2),就会按正常流程执行,程序的打印结果为:
methodA
methodB
main
finally代码块
finally代码块跟在try-catch后面,表示不管什么情况都会执行的语句。
public class WithFinally {
public void methodA(int money)throws SpecialException{
if(--money<=0) throw new SpecialException("Out of money");
System.out.println("methodA");
}
public static void main(String args[]){
try{
new WithFinally().methodA(1); //抛出SpecialException异常
System.out.println("main");
}catch(SpecialException e){
System.out.println("Wrong");
}finally{
System.out.println("Finally");
}
}
}
该程序的打印结果为:
Wrong
Finally
如果把main()方法中的“methodA(1)”改为“methodA(2)”,程序将正常运行,打印结果为:
methodA
main
Finally
异常类
所有异常类的祖先类为java.lang.Throwable类(可抛出的),它的实例表示具体的异常对象,可以通过throw语句抛出。Throwable类提供了访问异常信息的一些方法,常用的方法包括:
- getMessage():返回String类型的异常信息。
- printStackTrace():打印跟踪方法调用栈而获得的详细异常信息。在程序调试阶段,此方法可用于跟踪错误。
Throwable类有两个直接子类:
(1)Error类:表示单靠程序本身无法恢复的严重错误,比如内存空间不足,或者Java虚拟机的方法调用栈溢出。在大多数情况下,遇到这样的错误时,建议让程序终止。
(2)Exception类:表示程序本身可以处理的异常,本课程所有例子都是针对这类异常。当程序运行时出现这类异常,应该尽可能地处理异常,并且使程序恢复运行,而不应该随意终止程序。
JDK类库中所有的异常类:
Exception类
Exception类表示程序中出现的异常,可分为受检查异常和运行时异常。
运行时异常
RuntimeException类及其子类都称为运行时异常,这种异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws关键字声明抛出它,也会编译通过。
public int divide(int a,int b){
return a/b; //当参数b为0,抛出ArithmeticException
}
受检查异常
除了RuntimeException及其子类以外,其他的Exception类及其子类都属于受检查异常。
这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws关键字声明抛出它,否则编译不会通过。
void method1() throws IOException{} //合法
void method2(){//编译错误,必须捕获或声明抛出IOException
method1();
}
//合法,声明抛出IOException
void method3()throws IOException {
method1();
}
//合法,声明抛出Exception,IOException是Exception的子类
void method4()throws Exception {
method1();
}
void method5(){//合法,捕获IOException
try{
method1();
}catch(IOException e){System.out.println(e.getMessage());}
}
void method6(){//编译错误,必须捕获或声明抛出Exception
try{
method1();
}catch(IOException e){throw new Exception();}
}
void method7()throws Exception{//合法,声明抛出Exception
try{
method1();
}catch(IOException e){throw new Exception();}
}