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是提醒可能出异常,分清两种异常的处理要求,跟着小技巧写,就能写出稳当、好维护的代码。

相关推荐
ServBay2 小时前
告别面条代码,PSL 5.0 重构 PHP 性能与安全天花板
后端·php
孟沐3 小时前
Java 面向对象核心知识点(封装 / 继承 / 重写 / 多态)
后端
工边页字3 小时前
面试官:请详细介绍下AI中的token,越详细越好!
前端·人工智能·后端
LSTM974 小时前
确保文档安全:使用 C# 加密 Word 文档或设置文档权限
后端
孟沐4 小时前
Java 方法与方法重载
后端
Nyarlathotep01134 小时前
LinkedList源码分析
java·后端
小林coding4 小时前
专为程序员打造的简历模版来啦!覆盖前端、后端、测开、大模型等专业简历
前端·后端
UrbanJazzerati4 小时前
当网页翻页时,页码藏在哪里?——一次对分页机制的解密之旅
后端·面试
用户4490412095564 小时前
一次生产环境下的Redis连接耗尽问题排查与解决全过程
后端