为什么需要异常处理?

程序运行中出现异常就会终止程序,而我们可以通过捕获异常,处理异常,使异常后面的程序正常运行。

例如你写个程序读取文件,但是读到一半出错了。如果你不处理异常,那就会连后面的程序也不运行了。如果我们处理了异常,就让异常后面的程序段正常运行。例如关闭文件,释放资源。

Java异常类层次

java中try后面小括号和花括号区别 java里面try用来干嘛?_java

  • Error

是程序无法处理的错误。

  • Exception

是程序本身可以处理的异常

try,catch,finally关键字

  • try
    用于捕获异常。其后可以接零个或者多个catch快,如果没有catch快,则必须跟一个finally块
  • catch
    用于处理try捕获到的异常
  • finally
    无论是否捕获或处理异常,finally块的语句总会执行。如果try或catch块中有return语句,finally语句将在方法返回前被执行。

执行顺序

  1. try没有捕获到异常
  2. try捕获到异常,catch语句块里没有处理此异常的情况:此异常会抛给JVM处理,finally语句里的语句还是会执行,但是finally语句块之后的语句不会执行
  3. try捕获到异常,catch语句中有处理此异常的情况:出现异常以后,程序调到catch块中处理此异常的语句(处理其他异常的语句不会执行),然后不执行剩下的try中语句,直接到finally块,最后是finally快后面的语句。

throws抛出异常

如果一个方法可能会出现异常,但是没能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。

例如汽车在运行时可能会出现故障,汽车本身没办法(或者不愿意)处理这个故障,那就让开车的人来处理。

throws抛出异常规则

  1. 不可查异常。可以不使用throws关键字来声明,编译仍能顺利通过,运行时会被系统抛出。
  2. 可查异常。必须声明,否则会导致编译错误。
  3. 仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。
  4. 调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。
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 的值。