一、体系结构
Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
Java中的异常体系如图所示
Throwable有两个子类Error和Exception,分别表示错误和异常,其中Exception又分为受检异常(非运行时异常)和非受检异常(运行时异常RuntimeException)。他们之间的区别如下:
二、区别
1)Error和Exception
Error(错误)表示从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。
Exception(异常)表示需要捕捉或者需要程序进行处理的异常,它处理的是因为程序设计的瑕疵而引起的问题或者外在输入引起的一般性问题,
程序中应当尽可能去处理这些异常。
2)受检异常和非受检异常
Exception又分为受检异常和非受检异常
受检异常,也叫非运行时异常,是表示程序可以处理的异常,即表示程序可以修复(由程序自己接受异常并且做出处理)。
非受检异常,也叫运行时异常,表示
无法让程序恢复
的异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,因此,
编译器不检查
这些异常。
三、异常的捕获和处理
Java异常的捕获和处理涉及到五个关键字:try、catch、finally、throw、throws
1)异常的处理机制
一旦产生异常,则系统会自动产生一个异常实例化对象
此时如果存在try语句,则会自动找到匹配的catch语句执行,如果没有异常处理,则程序会退出,系统在控制台报告异常。
所有异常根据catch方法参数进行匹配异常的实例化对象,如果匹配成功,则由匹配成功的catch语句进行处理。
2)try、catch、finally
Java程序处理异常的格式如下:
try{
//可能出现异常的代码部分,表示要尝试运行代码,try语句块中代码受异常监控,其中代码发生异常时,会抛出异常对象
}catch(异常类型 异常变量){
//catch语句块会捕获try代码块中发生的异常并在其代码块中做异常处理,catch语句带一个Throwable类型的参数,表示可捕获异常类型。当try中出现异常时,catch会捕获到发生的异常,并和自己的异常类型匹配, 若匹配,则执行catch块中代码,并将catch块参数指向所抛的异常对象。catch语句可以有多个, 用来匹配多个中的一个异常,一旦匹配上后,就不再尝试匹配别的catch块了。
}catch(异常类型 异常变量){
//执行异常操作
}…
finally{
// finally语句块是紧跟catch语句后的语句块,这个语句块总是会在方法返回前执行, 而不管是否try语句块是否发生异常。并且这个语句块总是在方法返回前执行。
}
注意:
1.try、catch、finally均不能单独使用,三者可以组成try……catch、try……catch……finally、try……finally三种结构使用,其中catch语句可以有一个或多个,finally最多有一个。
2.多个catch语句的时候,只会匹配其中一个异常类并执行catch块代码,而不会再执行别的catch代码,并且匹配的顺序由上到下。
3.try、catch、finally三个代码块中的语句变量独立存在,不能相互访问
4.catch定义由上到下,异常范围必须由小到大或者同一级别。
5.运行时异常, catch中可以随意定义类型,程序运行时,会根据catch参数自动匹配。
6.非运行是异常,则catch中自定义的异常,在try代码块中必须存在,如果没有类似异常存在,则不允许被定义。
3)throws、throw
throws关键字主要在方法外部的方法声明部分用来声明方法可能会抛出的某些异常,方法中不处理异常,而交给调用处理。实际上对于java程序来讲,如果没有加入任何的异常处理,默认由虚拟机JVM进行异常处理。
throw关键字作用于方法内部,表示在程序中手动抛出一个throwable类型的异常,如果抛出了检查异常,则还应该在方法头部声明方法可能抛出的异常类型。该方法的调用者,也必须检查处理抛出的异常。
代码举例:
import java.awt.AWTException;
import java.awt.Robot;
import javax.swing.JFrame;
public class Test {
JFrame jf;
public static void main(String[] args) throws AWTException { // AWTException是检测性异常
Test t = new Test();
int v = t.div(20, 0);
System.out.println(v);
}
/**
* 做除法操作
*/
public int div(int a, int b) throws AWTException { // 声明方法内可能抛出的检查异常
// 会不会有异常情况出现???可能会有异常:除数为0
int result = 0;
try {
jf.setVisible(true);
result = a / b;
} catch (ArithmeticException e) { // ArithmeticException是运行时异常
throw new ArithmeticException(); // 出现ArithmeticException异常时抛出
} catch (NullPointerException e) {
e.printStackTrace(); // 在命令行打印异常信息在程序中出错的位置及原因
} finally {
// 必须(一定)会执行
System.out.println("执行了finally内容");
}
try {
Robot robot = new Robot();
} catch (AWTException e) {
throw new AWTException("異常問題"); // 抛出检查异常,需要在方法头部声明方法可能抛出的异常类型
}
return result;
}
}