为什么需要异常处理?
程序运行中出现异常就会终止程序,而我们可以通过捕获异常,处理异常,使异常后面的程序正常运行。
例如你写个程序读取文件,但是读到一半出错了。如果你不处理异常,那就会连后面的程序也不运行了。如果我们处理了异常,就让异常后面的程序段正常运行。例如关闭文件,释放资源。
Java异常类层次
- Error
是程序无法处理的错误。
- Exception
是程序本身可以处理的异常
try,catch,finally关键字
- try
用于捕获异常。其后可以接零个或者多个catch快,如果没有catch快,则必须跟一个finally块 - catch
用于处理try捕获到的异常 - finally
无论是否捕获或处理异常,finally块的语句总会执行。如果try或catch块中有return语句,finally语句将在方法返回前被执行。
执行顺序
- try没有捕获到异常
- try捕获到异常,catch语句块里没有处理此异常的情况:此异常会抛给JVM处理,finally语句里的语句还是会执行,但是finally语句块之后的语句不会执行
- try捕获到异常,catch语句中有处理此异常的情况:出现异常以后,程序调到catch块中处理此异常的语句(处理其他异常的语句不会执行),然后不执行剩下的try中语句,直接到finally块,最后是finally快后面的语句。
throws抛出异常
如果一个方法可能会出现异常,但是没能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。
例如汽车在运行时可能会出现故障,汽车本身没办法(或者不愿意)处理这个故障,那就让开车的人来处理。
throws抛出异常规则
- 不可查异常。可以不使用throws关键字来声明,编译仍能顺利通过,运行时会被系统抛出。
- 可查异常。必须声明,否则会导致编译错误。
- 仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。
- 调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。
void method1() throws IOException{} //合法
//编译错误,必须捕获或声明抛出IOException
void method2(){
method1();
}
//合法,声明抛出IOException
void method3()throws IOException {
method1();
}
//合法,声明抛出Exception,IOException是Exception的子类
void method4()throws Exception {
method1();
}
//合法,捕获IOException
void method5(){
try{
method1();
}catch(IOException e){…}
}
//编译错误,必须捕获或声明抛出Exception
void method6(){
try{
method1();
}catch(IOException e){throw new Exception();}
}
//合法,声明抛出Exception
void method7()throws Exception{
try{
method1();
}catch(IOException e){throw new Exception();}
}
throw抛出异常
throw总是出现在函数体中,用来抛出一个Throwable类型的异常。程序会在throw语句后立即中止,它后面的语句执行不到,然后再包含它的所有try块中,从里向外寻找含有与其匹配的catch子句的try块。
package Test;
import java.lang.Exception;
public class TestException {
static int quotient(int x, int y) throws MyException { // 定义方法抛出异常
if (y < 0) { // 判断参数是否小于0
throw new MyException("除数不能是负数"); // 异常信息
}
return x/y; // 返回值
}
public static void main(String args[]) { // 主方法
int a =3;
int b =0;
try { // try语句包含可能发生异常的语句
int result = quotient(a, b); // 调用方法quotient()
} catch (MyException e) { // 处理自定义异常
System.out.println(e.getMessage()); // 输出异常信息
} catch (ArithmeticException e) { // 处理ArithmeticException异常
System.out.println("除数不能为0"); // 输出提示信息
} catch (Exception e) { // 处理其他异常
System.out.println("程序发生了其他的异常"); // 输出提示信息
}
}
}
class MyException extends Exception { // 创建自定义异常类
String message; // 定义String类型变量
public MyException(String ErrorMessagr) { // 父类方法
message = ErrorMessagr;
}
public String getMessage() { // 覆盖getMessage()方法
return message;
}
}
Throwable类中的常用方法
- getCause():返回抛出异常的原因。如果cause不存在或未知,则返回null
- getMessage():返回异常的消息信息。
- printStackTrace():对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。