Java 异常体系完整笔记

一、概念

a) 异常 :程序运行过程中出现的非正常的情况。 b) 异常处理 :当异常出现时,执行预先准备好的程序。 c) 异常处理的必要性:减少用户损失,提升用户体验;捕获异常后可以给用户友好提示,避免程序直接崩溃。

二、异常的分类

Throwable:Java 语言中异常或者错误的父类,位于java.lang包。

i. Throwable 构造方法

  1. Throwable():无参数构造方法
  2. Throwable(String message):携带异常信息的构造方法

ii. Throwable 成员方法

  1. String getMessage():获取字符串类型异常信息
  2. void printStackTrace():打印栈追踪信息,查看异常发生完整调用链路

b) Error

ErrorThrowable的子类,代表错误

注意:Error 一般是程序本身无法恢复的严重错误,例如 JVM 内存不足、栈溢出java.lang.StackOverflowError。 开发中一般不处理 Error。

c) Exception

ExceptionThrowable的子类,代表异常,也是我们开发中重点处理的对象。

i. RuntimeException:运行时异常(非检查异常)

直接 / 间接继承RuntimeException,编译器不会检查,代码编译可以通过,运行时才会报错。

特点:可处理,也可以不处理;大多可以通过严谨代码规避。

常见运行时异常:

  • ArrayIndexOutOfBoundsException 数组下标越界
  • IndexOutOfBoundsException 集合下标越界
  • StringIndexOutOfBoundsException 字符串下标越界
  • NullPointerException 空指针异常
  • ClassCastException 类型转换异常
  • NumberFormatException 数字格式转换异常
ii. 非 RuntimeException:非运行时异常(受检异常 / 编译异常)

RuntimeException没有继承关系,编译器会强制检查。

特点:代码编译阶段就会报错,必须处理 ,否则无法编译通过。 示例:Class.forName("String");

iii. 异常产生的两种方式
  1. 自动产生异常
    • 原因:程序运行时执行错误代码,JVM 自动抛出异常
    • 结果:一旦异常抛出,后续代码不再执行,程序终止。
  2. 手动产生异常
    • 关键字:throw
    • 语法:throw new 异常类名("异常信息");
    • 位置:写在方法内部
    • 效果:类似return,终止当前方法,抛出异常。
iv. 异常的传递

Java 中的异常沿着方法调用链反向传递,如果全程没有捕获处理,最终会传递到 JVM,由 JVM 终止程序。

三、异常的处理

a) 消极处理异常:声明异常 throws

i. 关键字:throws ii. 位置:写在方法声明之后 iii. 语法

复制代码
修饰符 返回值类型 方法名(形参列表) throws 异常类名1,异常类名2{
    //方法体
}

iv. 注意:声明异常时,可以直接声明父类异常,代表抛出该父类下所有子类异常。 v. 作用:仅仅把异常责任向外抛出,推卸异常处理责任,最终交给调用者,如果调用者也不处理,异常最终给到 JVM,程序依旧会终止。

作用:让受检异常编译通过。

b) 积极处理异常:try-catch 捕获异常

i. 基础语法

复制代码
try{
    //可能出现异常的代码
}catch(异常类名 e){
    //异常发生后执行的代码
}

ii. 规则说明

  1. 只有try内部发生异常,catch块才会执行;无异常时,catch不执行。
  2. 一个try后面可以跟多个catch;发生异常时,从上往下依次匹配,匹配成功进入对应 catch。
  3. catch 可以写父类异常,利用多态捕获本类及其所有子类异常。
  4. 子类异常 catch 必须写在父类异常 catch 前面,否则编译报错。
  5. catch 块中可以捕获 try 代码里可能出现的受检异常。
  6. catch 块可以写任意运行时异常,哪怕 try 中不会出现该异常。

iii. finally:必须执行的语句块

  1. 语法

    try{
    //可能出现异常
    }catch(异常类 e){
    //异常处理
    }finally{
    //无论是否发生异常,都会执行的代码
    }

注意:开发中不建议在 finally 内部写 return;finally 典型用途:资源关闭,例如 IO 流、数据库连接等。

  1. 常用组合结构小结
  • try{}catch{}
  • try{}catch{}catch{}
  • try{}catch{}finally{}
  • try{}catch{}catch{}finally{}
  • try{}finally{}:不捕获异常,但是保证 finally 代码一定执行
  • 嵌套形式:try{ try{}catch{} } catch{}try{}catch{ try{}catch{} }try{}catch{}finally{ try{}catch{} }

注意:finally 不能单独使用,必须配合 try 或者 try-catch。


配套代码示例(可直接运行)

复制代码
public class ExceptionDemo {
    public static void main(String[] args) {
        try {
            int[] arr = {1,2,3};
            System.out.println(arr[5]); //数组越界,抛出异常
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("捕获到数组下标越界异常");
            System.out.println(e.getMessage());
            e.printStackTrace();
        } finally {
            System.out.println("finally块执行,用于关闭资源");
        }
    }
}

throws 声明异常示例

复制代码
public class ThrowsDemo {
    // 消极抛出异常,交给调用者处理
    public static void test() throws ClassNotFoundException {
        Class.forName("com.test.Demo");
    }

    public static void main(String[] args) {
        try {
            test();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

throw 手动抛出异常示例

复制代码
public class ThrowDemo {
    public static void checkAge(int age){
        if(age < 0){
            throw new RuntimeException("年龄不能为负数!");
        }
        System.out.println("年龄合法");
    }

    public static void main(String[] args) {
        checkAge(-5);
    }
}

面试小结

  1. ErrorException区别:Error 是严重错误,程序无法处理;Exception 是异常,可以捕获处理。
  2. 运行时异常和受检异常区别:受检异常编译期强制处理;运行时异常编译不检查。
  3. throwsthrow区别:throws在方法声明,声明抛出异常;throw在方法内部,手动抛出异常对象。
  4. finally 一定会执行吗?

大部分情况都会执行;唯一不执行场景:try内部执行System.exit(0)退出 JVM,finally 不会执行。

相关推荐
用户8356290780511 小时前
使用 Python 为 PDF 添加和管理超链接
后端·python
抠脚小弟1 小时前
Spring Task 定时任务详解:从入门到实战
java·后端·spring
千千寰宇1 小时前
[Python/测试] pytest:简洁、可扩展的 Python 测试框架
python·软件质量保障与测试
少陽君1 小时前
Python 并发编程:IO 等待用线程/asyncio,CPU 计算才用进程
数据库·python·php
2601_962284501 小时前
Python 和Java 哪个更适合做自动化测试?
java·自动化测试·python·接口测试·性能测试
liliangcsdn2 小时前
因子权重矩阵处理-滞回缓冲带+降频稳定化动态重选
开发语言·python·算法
随遇而安zx2 小时前
【多线程】---AQS 原理 知识点(设计思想与源码深度解析)
java·多线程·aqs
LXMXHJ2 小时前
springboot中的线程操作
java·spring boot·后端·线程
泡泡鱼(敲代码中)2 小时前
Python语法技术学习笔记
开发语言·笔记·python·学习·pycharm