Java 基础(十)异常

Java异常处理核心知识点总结(学习笔记)

在Java编程中,异常处理是保证程序健壮性的关键机制。它能让程序在遇到错误时不会直接崩溃,而是优雅地处理问题。本文结合课堂代码,系统梳理Java异常的体系结构、分类、处理方式及自定义异常,补充关键细节和最佳实践。

一、异常的体系结构

Java中所有的异常和错误都继承自Throwable类,它是异常体系的根节点。整体结构如下:

复制代码
Throwable
├── Error(错误)
│   ├── StackOverflowError(栈溢出)
│   └── OutOfMemoryError(堆溢出)
└── Exception(异常)
    ├── RuntimeException(运行时异常/非受检异常)
    │   ├── NullPointerException(空指针异常)
    │   ├── ArrayIndexOutOfBoundsException(数组越界异常)
    │   ├── ClassCastException(类型转换异常)
    │   └── ArithmeticException(算术异常)
    └── 其他Exception(非运行时异常/受检异常)
        ├── FileNotFoundException(文件未找到异常)
        ├── IOException(IO异常)
        └── SQLException(数据库异常)

1. Error(错误)

Error是程序无法处理的严重问题,通常由JVM底层抛出,程序只能尽量避免。

  • StackOverflowError:栈溢出,常见于递归调用过深(如无限递归)。
  • OutOfMemoryError:堆溢出,常见于创建过大的对象或内存泄漏。

2. Exception(异常)

Exception是程序可以处理的错误,分为两类:

  • 运行时异常(非受检异常):由程序逻辑错误引起,编译时不强制要求处理。例如空指针、数组越界。
  • 非运行时异常(受检异常):编译时必须处理,否则程序无法通过编译。例如文件未找到、IO异常。

二、异常的处理方式

Java提供了两种核心的异常处理方式:try-catch-finally(捕获处理)和throws(向上抛出)。

1. try-catch-finally:捕获并处理异常

这是最常用的异常处理方式,结构如下:

java 复制代码
try {
    // 可能抛出异常的代码
} catch (异常类型1 e) {
    // 处理异常类型1
} catch (异常类型2 e) {
    // 处理异常类型2(子类异常在前,父类在后)
} finally {
    // 无论是否发生异常,都会执行的代码(通常用于关闭资源)
}
执行流程
  1. 先执行try块中的代码。
  2. 如果try块抛出异常,跳转到匹配的catch块处理。
  3. 最后执行finally块(即使trycatch中有returnfinally也会执行)。
代码示例(结合课堂代码)
java 复制代码
public class Main {
    public static void main(String[] args) {
        run();
    }

    public static void run() {
        try {
            // 手动抛出一个异常
            throw new Exception("自定义异常");
        } catch (Exception e) {
            // 捕获并处理异常,打印异常信息
            System.out.println(e.getMessage());
        }
    }
}
注意事项
  • 多个catch块的顺序:子类异常必须写在父类异常前面,否则父类会把子类异常"拦截"掉。
  • finally的特殊情况 :如果try块中执行了System.exit(0)finally块不会执行(因为JVM直接退出了)。
  • 资源关闭 :Java 7+推荐使用try-with-resources自动关闭资源,更简洁安全。

2. throws:向上抛出异常

如果当前方法不想处理异常,可以使用throws关键字将异常抛给调用者处理。

java 复制代码
// 方法声明中使用throws,抛出多个异常用逗号分隔
public static void main(String[] args) throws Exception {
    // 调用run(),run()抛出的异常由main()的调用者(JVM)处理
    run();
}

public static void run() throws Exception {
    // 不处理异常,直接抛出
    throw new Exception("自定义异常");
}
throws和throw的区别
关键字 位置 作用
throws 方法声明上 表示该方法可能抛出异常,由调用者处理
throw 方法体内 手动抛出一个具体的异常对象

三、自定义异常

Java内置的异常类可能无法满足所有业务场景,我们可以通过继承ExceptionRuntimeException来自定义异常。

自定义异常的步骤

  1. 定义一个类,继承Exception(受检异常)或RuntimeException(运行时异常)。
  2. 提供构造方法(无参构造和带异常信息的构造)。

完整代码示例

java 复制代码
// 1. 自定义受检异常(继承Exception)
public class BusinessException extends Exception {
    // 无参构造
    public BusinessException() {}
    
    // 带异常信息的构造
    public BusinessException(String message) {
        super(message);
    }
}

// 2. 使用自定义异常
public class CustomExceptionTest {
    public static void main(String[] args) {
        try {
            checkAge(-1);
        } catch (BusinessException e) {
            System.out.println("捕获到业务异常:" + e.getMessage());
        }
    }
    
    // 检查年龄的方法,年龄不能为负数
    public static void checkAge(int age) throws BusinessException {
        if (age < 0) {
            // 抛出自定义异常
            throw new BusinessException("年龄不能为负数:" + age);
        }
        System.out.println("年龄合法:" + age);
    }
}

四、最佳实践总结

  1. 优先捕获具体异常 :不要直接捕获Exception,应该捕获具体的子类异常,便于定位问题。
  2. 不要忽略异常catch块中至少要打印异常信息(e.printStackTrace()),不要留空。
  3. 使用try-with-resources :处理IO流等资源时,优先使用try-with-resources自动关闭资源。
  4. 自定义异常要有意义 :自定义异常类名要能体现业务场景(如BusinessExceptionUserNotFoundException)。

异常处理是Java编程的基本功,掌握它能让你的程序更健壮、更易维护。多写多练,结合实际场景理解异常的处理逻辑,就能熟练运用啦。

相关推荐
和小潘一起学AI2 小时前
Python导入私有模块(企业级方案)
开发语言·python
_F_y2 小时前
C++11 异步操作实现线程池
java·jvm·c++
Irene19912 小时前
(课堂笔记)Oracle 表关联:连接类型、数据发散、自关联、同环比计算
oracle·连接
!停2 小时前
C++入门STL容器Vector使用基础,深挖 Vector替代 C 语言繁琐容器的利器
开发语言·c++
小何code2 小时前
【Python零基础入门】第4篇:Python变量与数据类型详解
开发语言·python
xiaoshuaishuai82 小时前
C# 数字资源分发
开发语言·c#
techdashen2 小时前
用自家产品构建自家产品:Cloudflare Images 的工程架构解析
开发语言·架构·rust
Lumos_7772 小时前
Linux -- 共享内存
java·linux·运维
笑不语2 小时前
从共病网络到可解释 AI:同济医院 10 分 SCI 全流程复现(R 语言)
开发语言·人工智能·r语言