一、引言在Java里有时候我们的代码没有报错但是却运行不了比如说当我们写出int a10; System.out.println(a/0);这样子的代码的时候编译器并不会报错但在实际运行的过程当中会出现这种情况而ArithmeticException便是异常。异常其实本质就是一种类我们称为异常类。除上面的算术异常还有数组越界异常空指针异常等。二、异常的体系结构我们所有的异常都是继承与同一个父类Throwable这个类的然后这个类有俩个子类分别是Error和Exception。先介绍Error类Error表示Java运行时JVM内部的错误和资源耗尽的错误一旦发生了就无力回天了。而Exception及其子类程序员可以通过代码处理使得程序继续运行下去Exception他又有好多的子类继承比如刚才的ArithmeticException类便是继承与RuntimeException而这个又继承与 Exception类。这张图就是我们异常的一个体系结构三、异常的分类1、运行时异常RuntimeException运行时异常也被称为不可查异常由程序逻辑错误导致如空指针、数组越界、算术异常编译器不强制捕获 / 声明建议通过代码逻辑规避。子类有NullPointerException空指针、ClassCastException类型转换错误、IllegalArgumentException参数非法等等。2、编译时异常Checked Exception编译时异常也称为可查异常编译器强制要求捕获或声明抛出如 IO 异常、数据库异常代表程序可处理的外部异常如文件不存在、数据库连接失败。子类有IOExceptionIO 异常、SQLException数据库异常、ClassNotFoundException类找不到等等。四、如何处理异常关于如何处理异常我们要介绍Java为我们提供的三个关键字分别是try和catch以及finally这三个便是我们用来处理异常的语法下面用代码来介绍如何去使用。try { // 可能抛出异常的代码 int result 10 / 0; // 示例除零异常 } catch (ArithmeticException e) { // 捕获特定异常此处为算术异常 System.err.println(发生算术异常: e.getMessage()); } catch (Exception e) { // 捕获其他未明确的异常 System.err.println(未知异常: e.getMessage()); } finally { // 无论是否发生异常都会执行的代码 System.out.println(执行finally块); }以上代码的运行结果会出现以下情况可以看到我们捕获了算术异常并进行了处理在使用的时候我们只需要把可能发生异常的代码放入try里面即可之后catch里面的内容只有捕获到了异常才会被执行而finally里面的内容是不管有没有捕获到异常都会被执行通常用来善后使用并且finally 在 return 前执行从上面的代码可以看出设计了俩个异常捕获但实际上不管我们要捕获多少异常都只会执行程序发生的第一个异常比如上面的代码只捕获了一个算术异常并没有捕获到下面的Exception但如果我们把Exception放到上面的话就会先捕获Exception异常但是Exception是很多异常的父类我们确定不了具体的异常类型所以在捕获的时候优先把父类给放到下面避免无法确定异常的具体类型。五、异常的抛出与声明下面我要介绍俩个关键字分别是throws和throw他们长的虽然十分相似但作用是不一样的先说throw他的作用是手动抛出异常。1、throwpublic int getElement(int[] array){ if(null array){ throw new NullPointerException(传递的数组为null); }这里就抛出了一个空指针异常将这个错误信息告诉调用者语法形式就是这样throw newXXXException(异常产生的原因);关于throw有几个注意的点1、throw必须写在方法体内部2.抛出的对象必须是Exception或者Exception的子类对象3.如果抛出的是RunTimeException或者RunTimeException的子类则可以不用处理直接交给JVM来处理4.如果抛出的是编译时异常用户必须处理否则无法通过编译5.异常一旦抛出其后的代码就不会执行2、throws这个关键字是用来声明异常的。写在方法的最右边声明这个方法可能会抛出的异常import java.io.FileReader; import java.io.IOException; public class FileProcessor { // 使用 throws 声明可能抛出的 IOException public void readFile(String filePath) throws IOException { FileReader reader new FileReader(filePath); int character; while ((character reader.read()) ! -1) { System.out.print((char) character); } reader.close(); } public static void main(String[] args) { FileProcessor processor new FileProcessor(); try { processor.readFile(example.txt); } catch (IOException e) { System.err.println(文件读取错误: e.getMessage()); } } }我们是可以声明多个异常的但异常之间要用“”隔开。这个关键字主要用于提醒调用者处理异常如果不处理的话就要用throws继续抛出最后交给JVM处理。主要事项1、检查型异常如IOException必须被捕获或声明抛出2、运行时异常如NullPointerException不需要声明3.、方法内部如果抛出了多个异常throws之后必须跟多个异常类型之间用逗号隔开如果抛出多个异常类型 具有父子关系直接声明父类即可。4、throws必须跟在方法的参数列表之后5、调用声明抛出异常的方法时调用者必须对该异常进行处理或者继续使用throws抛出3、二者核心区别对比维度throw手动抛出异常throws声明异常核心作用手动触发 / 抛出具体的异常对象明确告知程序 “此处发生了某个异常”声明当前方法可能会抛出的异常类型提醒调用者需要处理这些异常语法位置写在方法体内部可在条件判断、逻辑执行中使用写在方法声明的末尾参数列表之后方法体之前操作对象操作的是异常对象必须是 Exception 或其子类的实例如throw new NullPointerException()操作的是异常类名声明可能抛出的异常类型如public void test() throws IOException使用次数一个方法体中可根据逻辑多次使用如不同条件抛不同异常一个方法声明中只能写一次但可声明多个异常类用逗号分隔如throws IOExcepiton, SQLException执行逻辑一旦执行其后的代码立即停止执行直接跳转到异常处理逻辑仅做 “声明”不会中断方法执行方法内代码仍正常运行仅提醒调用者处理风险异常类型要求可抛运行时异常无需处理或编译时异常必须手动处理 / 声明声明运行时异常编译器无强制要求声明编译时异常调用者必须处理catch 或继续 throws六、自定义异常我们在写代码的过程中不一定我们需要的异常Java不一定全部都有比如我们要声明一个下标异常Java就没有这个时候就需要我们自己去定义一个异常。想要定义一个异常的话其实就是写一个类让它去继承异常类Exception就可以了具体实现见下面代码// 自定义异常类继承Exception class InvalidAgeException extends Exception { public InvalidAgeException(String message) { super(message); } } // 使用自定义异常的类 public class CustomExceptionDemo { static void validateAge(int age) throws InvalidAgeException { if (age 18) { throw new InvalidAgeException(Age must be 18 or older); } System.out.println(Age validation passed); } public static void main(String[] args) { try { validateAge(15); // 测试小于18的年龄 } catch (InvalidAgeException e) { System.out.println(Caught custom exception: e.getMessage()); } } }代码说明创建自定义异常类继承自Exception类检查型异常或RuntimeException类非检查型异常提供构造函数传递异常信息抛出异常在业务逻辑中使用throw关键字抛出异常实例方法声明中用throws指定可能抛出的异常类型捕获异常使用try-catch块处理可能抛出的异常通过getMessage()获取异常信息以上代码的输出结果会是​​​Caught custom exception: Age must be 18 or older注意事项1、在我们定义的异常里面要实现一个带有String类型参数的构造方法参数含义出现异常的原因​​​​​​​2、自定义异常通常会继承自Exception或者RuntimeException3、继承自Exception的异常默认是受查异常4、继承自RuntimeException的异常默认是非受查异常