概述
Java异常处理是一种机制,用于在程序运行过程中捕获和处理可能发生的异常情况,以确保程序的正常执行或提供有意义的错误信息
异常体系
Java中的所有异常都是从 Throwable 类派生的,其有两个主要的子类:Exception 和 Error
1.Exception(异常)
Exception 类表示程序中可被捕获和处理的异常情况。它分为两个主要的子类:受检查异常(Checked Exception)和不受检查异常(Unchecked Exception)
1.1.受检查异常
受检异常是指在编译时需要处理的异常。程序必须显式地声明并处理这些异常,否则无法通过编译。受检异常通常表示外部因素导致的问题,如输入/输出操作、数据库操作等。受检异常是Exception类的直接子类,包括IOException、SQLException等。
1.2.不受检查异常
不受检查异常指在运行时可能出现的异常,不需要在编译时强制处理。这些异常通常是由程序错误导致的,如空指针引用、数组越界等。非受检异常是RuntimeException类的子类,包括NullPointerException、ArrayIndexOutOfBoundsException等
2.Error(错误)
Error类表示的是不可恢复的错误,通常由系统或运行时环境引起,例如内存不足、堆栈溢出等。与Exception类不同,Error类通常不应该被程序捕获和处理,而是由Java虚拟机(JVM)或底层系统来处理
异常处理
1.throw关键字
格式:
throw new 异常类名(参数);
作用: throw关键字用于在代码中特定位置显式地抛出异常,并且可以被上层调用者或异常处理机制捕获和处理
public class Demo1 {
public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println("Result: " + result);
} catch (RuntimeException e) {
System.out.println("An error occurred: " + e.getMessage());
}
}
public static int divide(int dividend, int divisor) {
if (divisor == 0) {
throw new ArithmeticException("Division by zero is not allowed");
}
return dividend / divisor;
}
}
An error occurred: Division by zero is not allowed
关于throw关键字几点说明:
throw关键字必须出现在方法内部
throw关键字抛出的对象必须是Exception类及其子类对象
如果throw关键字抛出的是不受检查异常,可以不对抛出的异常对象进行显示处理,异常会默认交给JVM处理(打印异常对象、中断程序)
如果throw关键字抛出的是受检查异常,则必须对异常进行显式处理,要么通过throws关键字将异常交由方法的调用者进行处理,要么通过try-catch语句捕获处理
2.throws关键字
格式:
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2,...{ ... }
作用: throws关键字用于在方法声明中指定可能抛出的异常类型。换句话说, 是告知方法的调用者,该方法可能会抛出指定类型的异常,从而让调用者在调用方法时做好相应的异常处理准备
public class Demo1 {
public static void main(String[] args) throws IOException {
int result = readFile();
System.out.println("Result: " + result);
System.out.println("fuck");
}
public static int readFile() throws IOException {
throw new IOException("IO错误");
}
}
关于 throws 关键字几点说明:
throws关键字必须写在方法声明处
throws关键字后边声明的对象必须是Exception类及其子类
方法内部如果抛出了多个异常,那么throws后面也必须声明多个异常。如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可(因此throws可以只声明一个Expection异常)
调用一个声明异常的方法,就必须处理声明的异常。要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM;要么通过try-catch自己处理异常
3.try-catch-finally语句
格式:
try{ 可能会出现异常的代码 }catch(异常类型 e){ 处理异常 // 例如: 记录日志、打印异常信息、继续抛出异常 }finally{ 无论是否出现异常都会执行 // 例如: 资源释放 }
作用:
-
try块:用于捕获异常
-
catch块:用于处理try捕获到的异常
-
finally块:⽆论是否捕获或处理异常, finally块⾥的语句都会被执行(常用于资源释放)
关于 try-catch-finally 语句的几点说明:
try块不可单独出现: try块后可接零个或多个catch块,如果没有catch块,则必须跟⼀个finally块
当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行
当try块和finally块中都有return语句时,在返回之前finally块的内容将被执行,并且finally块的返回值将会覆盖原始的返回值
自定义异常
如果Java提供的异常类不够我们使用,需要根据自己业务的异常情况来定义异常类
格式:
public class 异常方法名 extends Exception(或者RuntimeException) { 添加一个空参数的构造方法 //所有异常类都有带异常信息的构造方法,方法内部会调用父类带异常信息的构造方法,让父类来处理异常信息 添加一个带异常信息的构造方法 }
示例:
public class InvalidInputException extends Exception {
public InvalidInputException(String message) {
super(message);
}
}
说明:
自定义异常类命名一般都是以Exception结尾,说明该类是一个异常类
自定义异常类,必须继承Exception或RuntimeException。如果继承Exception,那么自定义的异常类就是一个编译期异常。如果继承RuntimeException,那么自定义的异常类就是一个运行期异常,可以无需处理,默认交由虚拟机进行处理(中断处理)