Java异常处理知识点整理(大白话版)

一、什么是异常?

异常就是程序运行的时候,出现的意外情况,比如做除法时把除数设成0、想操作一个对象却发现它是空的、想打开一个文件却找不到,这些情况都会打断程序的正常运行,要是不管它,程序就会直接崩溃。

二、异常分两类,处理要求不一样

  • 受检异常:Java强制要求必须处理的异常。要么用try-catch接住处理,要么用throws告诉调用者"我可能出这个问题,你自己处理",不处理的话,代码都编译不过,没法运行。
  • 非受检异常:Java不强制处理的异常,比如除零异常、空指针异常。这些大多是写代码时的小失误,Java允许不专门处理,要么被上层代码处理,要么直接导致程序崩溃,相当于提醒你下次别犯这错。

三、try-catch-finally:处理异常的"三件套"

这是处理异常最基础的方式,三者分工明确,用法很简单,就像处理生活中的意外一样。

3.1 三者各自的作用

组成部分 大白话作用 执行规则
try 装可能出问题的代码(比如做除法、打开文件) 没异常:从头到尾执行完;有异常:执行到出问题的地方就停,跳去看catch
catch 接住并处理异常(比如提示"除数不能为0") 只有try里的异常和catch声明的类型一样,才会执行;类型不匹配就不执行,程序后续会崩溃
finally 做收尾工作(比如关闭文件、清理资源) 不管有没有异常、catch有没有接住,一定执行(除非强制关掉程序)

3.2 三种执行场景(一看就懂)

  • 场景1:try里没异常 → 跑完try,跳过catch,执行finally,继续跑后面的代码
  • 场景2:try里出异常,且catch能接住 → 执行到异常点停,执行catch,再执行finally,继续跑后面的代码
  • 场景3:try里出异常,catch接不住 → 执行到异常点停,跳过catch,执行finally,然后程序崩溃,后面的代码不跑

四、throw和throws:别搞混这两个"抛异常"的关键字

两者都和抛异常有关,但用法完全不一样,用表格一对比就清楚,不用死记硬背。

关键字 写在哪个位置 怎么写(简单示例) 大白话作用
throw 方法里面 throw new 异常对象(); 主动制造一个具体的异常(比如发现除数是0,主动抛出"除数不能为0"),是异常的源头
throws 方法声明处(方法名后面) 方法名(参数) throws 异常类型; 告诉调用者:"我可能会出某种异常,你要么自己处理,要么继续告诉别人"

4.1 必看注意点

  • throw后面必须跟具体的异常对象(比如throw new ArithmeticException("除数不能为0")),不能只写异常类型;
  • throws后面必须跟异常类型(可多个,用逗号隔开),不能跟异常对象;
  • 如果用throw抛出受检异常(Java强制处理的),要么在方法里用try-catch处理,要么用throws声明,不然代码编译不过;
  • 抛出非受检异常(比如除零异常),可以不用写throws,Java会自动往上传递。

五、完整可运行代码示例(大白话注释)

下面的代码包含了所有知识点,注释都是大白话,直接复制到Java编辑器就能运行,跑一遍就懂所有逻辑。

csharp 复制代码
/**
 * Java异常处理大白话演示
 * 包含:try-catch-finally、throw、throws、两种异常处理
 * 新手也能看懂的注释
 */
public class ExceptionDemo {

    public static void main(String[] args) {
        // 测试1:没出异常的情况
        System.out.println("===== 测试1:没出异常 =====");
        try {
            divide(12, 4); // 除数不是0,没异常
            System.out.println("try里的代码跑完了,没出问题");
        } catch (ArithmeticException e) {
            System.out.println("捕获到异常:" + e.getMessage()); // 不会执行
        } finally {
            System.out.println("finally执行:清理资源\n"); // 必执行
        }

        // 测试2:出异常但被catch接住
        System.out.println("===== 测试2:出异常但被接住 =====");
        try {
            divide(12, 0); // 除数是0,出异常
            System.out.println("try里的代码跑完了,没出问题"); // 不会执行
        } catch (ArithmeticException e) {
            System.out.println("捕获到异常:" + e.getMessage()); // 执行处理
        } finally {
            System.out.println("finally执行:清理资源\n"); // 必执行
        }

        // 测试3:出异常但catch接不住
        System.out.println("===== 测试3:出异常但接不住 =====");
        try {
            divide(12, 0); // 出除零异常
        } catch (NullPointerException e) {
            System.out.println("捕获到空指针异常"); // 类型不匹配,不执行
        } finally {
            System.out.println("finally执行:清理资源"); // 必执行
        }
        System.out.println("测试3执行完毕"); // 程序崩溃,不会执行

        // 测试4:受检异常处理
        System.out.println("===== 测试4:受检异常处理 =====");
        try {
            checkException(); // 调用声明了受检异常的方法,必须用try-catch
        } catch (Exception e) {
            System.out.println("捕获到受检异常:" + e.getMessage());
            throw new RuntimeException(e); // 可选:转成非受检异常,不用层层写throws
        } finally {
            System.out.println("finally执行:清理资源");
        }
    }

    /**
     * 除法方法,演示非受检异常的throw和throws
     * @param num1 被除数
     * @param num2 除数
     * @throws ArithmeticException 告诉调用者:我可能出除零异常
     */
    public static void divide(int num1, int num2) throws ArithmeticException {
        if (num2 == 0) {
            // 主动抛出除零异常,提示用户输错了
            throw new ArithmeticException("除数不能为0,你输错啦!");
        }
        System.out.println("除法结果:" + num1 + " ÷ " + num2 + " = " + (num1 / num2));
    }

    /**
     * 演示受检异常的throw和throws
     * @throws Exception 告诉调用者:我可能出受检异常
     */
    public static void checkException() throws Exception {
        boolean hasError = true; // 模拟业务执行失败
        if (hasError) {
            // 主动抛出受检异常,说明业务没成功
            throw new Exception("模拟受检异常:业务没执行成功");
        }
        System.out.println("业务执行成功"); // 不会执行
    }
}

六、异常处理小技巧(大白话版)

  • 尽量精准捕获异常:能捕获"除零异常",就别直接捕获所有异常(Exception),不然找不到具体问题在哪;
  • 受检异常嫌麻烦可以转:把受检异常包装成非受检异常(throw new RuntimeException(e)),不用层层写throws;
  • finally一定要用对:打开文件、连接数据库后,不管有没有异常,都要在finally里关掉,避免浪费资源;
  • 分工要明确:底层方法(比如divide)只负责抛异常(throws),上层调用者(比如main)负责处理异常(try-catch),代码更清晰。

七、总结

异常处理的核心就是"不让程序崩溃",遇到意外要么接住处理,要么告诉别人处理。try-catch-finally是基础工具,throw是主动抛具体异常,throws是提醒可能出异常,分清两种异常的处理要求,跟着小技巧写,就能写出稳当、好维护的代码。

相关推荐
LucianaiB13 分钟前
参加高德 AI 发布会的一点感受:地图,正在变成 AI 的行动入口
后端
属于自己的天空13 分钟前
一个文件让 Claude Code 理解你的项目:CLAUDE.md 从入门到精通
后端
jiangbo_dev19 分钟前
还在手搓分布式事务?我把 Saga + Outbox 模板化后,新服务接入从 5 天压到 1 天
后端
BING_Algorithm22 分钟前
深入理解JVM垃圾回收
jvm·后端·面试
RainCity42 分钟前
Java Swing 自定义组件库分享(六)
java·笔记·后端
techdashen1 小时前
深入 Rust enum 的内存世界
开发语言·后端·rust
龙码精神1 小时前
TimescaleDB 物联网设备属性历史数据表设计及常用SQL文档
后端
小小小小宇1 小时前
Go 后端锁机制详解
后端
挖坑的张师傅1 小时前
你的仓库 Agent Ready 了吗?
后端
客场消音器2 小时前
如何使用codex进行UI重构,让AI开发的前端页面不再千篇一律
前端·后端·微信小程序