楼层: 首页/ 软件技术/ Java 基础/ 异常处理:程序出错了怎么办
06

异常处理:程序出错了怎么办

Exceptions · try-catch-finally · try-with-resources

程序跑挂了,不能直接蓝屏给用户看。异常(Exception)机制就是 Java 的"保险丝":出错时抛出一个异常对象,你可以选择抓住它、妥善处理,或者继续往上甩。写网络、文件、数据库代码,一半时间都在跟异常打交道。

论受检异常 vs 非受检异常

受检异常(checked):编译器逼着你处理,不 catch 或不 throws 就编译不过。比如 IOException(读文件可能失败)、SQLException(数据库可能断)。

非受检异常(unchecked / RuntimeException):编译器不管,出了事运行时才炸。比如 NullPointerException(空指针,简称 NPE)、IllegalArgumentException、数组越界。

口诀:能预料的外部问题(文件、网络、数据库)用受检异常;自己代码的 bug(空指针、下标越界)是运行时异常,改代码修,别瞎 catch。

try-catch-finally 与 try-with-resources(Java 7+)

import java.io.*;

public class ExceptionDemo {
    public static void main(String[] args) {
        // 老写法:finally 里手动关流,忘了关就资源泄漏,啰嗦还容易错
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("a.txt"));
            System.out.println(reader.readLine());
        } catch (IOException e) {
            System.out.println("读文件失败:" + e.getMessage());
        } finally {
            try {
                if (reader != null) reader.close();
            } catch (IOException ignored) {}
        }

        // 新写法(推荐):try-with-resources,自动关闭实现了 AutoCloseable 的资源
        try (BufferedReader r = new BufferedReader(new FileReader("a.txt"))) {
            System.out.println(r.readLine());
        } catch (IOException e) {
            System.out.println("读文件失败:" + e.getMessage());
        }
    }
}

异常家族谱系:Exception 和 Error 是两码事

看到抛异常先归类:是 Exception(你代码能处理的)还是 Error(JVM 自己崩了,你救不了)。

类型代表 & 怎么对待
Exception程序层面的异常,catch 住继续活。又分受检(编译逼你处理)和 RuntimeException(运行时才炸)。
ErrorOutOfMemoryError、StackOverflowError——JVM 自身不行了,catch 了也没用,别浪费时间。
RuntimeException 常见兄弟NPE、IllegalArgumentException、IndexOutOfBoundsException、ConcurrentModificationException。

自定义异常 + throw / throws 的区别

// 自定义异常:业务上"余额不足"这种错,自己定义更清晰
class NotEnoughMoneyException extends Exception {
    public NotEnoughMoneyException(String msg) { super(msg); }
}

class Account {
    private int balance;
    // throws 是在方法签名上"声明":我可能甩这个异常出去,调用者你看着办
    public void withdraw(int money) throws NotEnoughMoneyException {
        if (money > balance) {
            // throw 是"当场抛出"一个异常对象
            throw new NotEnoughMoneyException("余额只剩" + balance);
        }
        balance -= money;
    }
}
NPE 是 Java 程序员的一生之敌

NullPointerException 就是你对一个 null(空)的对象调用了方法。消除办法:① 返回值别随便给 null,宁可返回空集合 Collections.emptyList();② 判空用 Objects.requireNonNull(x) 或 Optional;③ 调用链上每一步都想一下"这一步会不会是 null"。Java 14+ 还引入了 空指针友好提示,会直接告诉你是哪一步是 null,排错快很多。

章末面试 · 异常处理(4 题)

1.(概念题)受检异常和非受检异常区别?各举两个例子。

查看答案

答案:受检异常编译器逼你 catch/throws(IOException、SQLException);非受检异常是 RuntimeException 及其子类(NullPointerException、IllegalArgumentException),编译不管。

2.(代码题)throw 和 throws 区别?

查看答案

答案:throw 在方法体里当场抛出一个异常对象;throws 在方法签名上声明"我可能甩这个异常出去",调用者看着办。

3.(代码题)try-with-resources 比 try-finally 好在哪?什么类能放进去?

查看答案

答案:自动关闭资源,不用手写 finally close,不会漏。放进去的类必须实现 AutoCloseable(或 Closeable)。

4.(概念题)Exception 和 Error 区别?看到 OutOfMemoryError 该 catch 吗?

查看答案

答案:Exception 是程序层面可处理的异常;Error 是 JVM 自身崩了(OOME、StackOverflow),catch 了也救不了。别 catch Error,先修堆大小或修代码。