Java finally案例怎么实操使用

wen java案例 23

本文目录导读:

Java finally案例怎么实操使用

  1. 案例一:最基本的资源清理(最常用)
  2. 案例二:即使 try 里有 return,finally 也会执行
  3. 案例三:模拟数据库连接释放(联网操作)
  4. 最佳实操原则(适合面试和写汇报)

我们来通过几个生动的案例,手把手实操 finally 的使用。finally 的核心作用是:无论 try 块中是否发生异常,finally 块中的代码都一定会被执行,它通常用于释放资源(如关闭文件、数据库连接、释放锁等)。

重要前提: 只有一种情况 finally 块不会执行:在 trycatch 块中执行了 System.exit(0)(强制退出JVM)。


最基本的资源清理(最常用)

场景: 你打开了一个文件(或数据库连接),必须确保关闭它,哪怕中间出错了。

import java.io.*;
public class FinallyDemo1 {
    public static void main(String[] args) {
        BufferedReader reader = null;
        try {
            // 1. 尝试打开文件
            reader = new BufferedReader(new FileReader("test.txt"));
            String line = reader.readLine();
            System.out.println("文件内容: " + line);
            // 假设这里故意让分母为0,抛出异常
            int result = 10 / 0; 
        } catch (FileNotFoundException e) {
            System.out.println("捕获到异常: 文件未找到!");
        } catch (IOException e) {
            System.out.println("捕获到异常: 读取文件错误!");
        } catch (ArithmeticException e) {
            System.out.println("捕获到异常: 数学运算错误!");
        } finally {
            // 2. 无论上面是否出错,finally 确保在这里关闭文件
            System.out.println("【finally】正在执行清理工作...");
            if (reader != null) {
                try {
                    reader.close();
                    System.out.println("文件成功关闭。");
                } catch (IOException e) {
                    System.out.println("关闭文件时出错: " + e.getMessage());
                }
            }
        }
        System.out.println("程序继续执行(即使发生了异常,只要被catch了)");
    }
}

运行结果分析(如果你当前目录下没有 test.txt 文件):

捕获到异常: 文件未找到!
【finally】正在执行清理工作...
程序继续执行(即使发生了异常,只要被catch了)

关键点: 即使在第一个 catch 就捕获了异常并退出了 try 块,finally 依然会在程序继续向下执行之前运行。


即使 try 里有 return,finally 也会执行

场景: 这是一个容易混淆的面试题。try 快中有 return 语句,finally 会在返回之前执行。

public class FinallyReturnDemo {
    public static int testFinally() {
        int result = 1;
        try {
            System.out.println("执行 try 块");
            // 发生异常,会跳到 catch
            Integer.parseInt("abc"); 
            result = 2;
            return result; // 这行其实执行不到,因为上面抛异常了
        } catch (NumberFormatException e) {
            System.out.println("捕获异常: " + e.getMessage());
            result = 3;
            return result; // 这里有一个return
        } finally {
            System.out.println("执行 finally 块 (result当前值=" + result + ")");
            result = 4; // 修改了result,但注意:返回的是return语句的“快照”
            // 如果finally里也有return,会覆盖catch里的return!
        }
    }
    public static void main(String[] args) {
        int value = testFinally();
        System.out.println("main方法接收到的返回值: " + value);
    }
}

运行结果:

执行 try 块
捕获异常: java.lang.NumberFormatException: For input string: "abc"
执行 finally 块 (result当前值=3)
main方法接收到的返回值: 3

深度理解:

  1. catch 中的 return result; 先把 result 的值(此时是3)保存在一个临时位置。
  2. finally 中的 result = 4; 修改了变量,但不会影响已经保存的返回值3
  3. 特例: 如果你把 finally 里的 result = 4; 改成 return 100;catch 里的 return 会失效,最终返回 100永远不要在 finally 中使用 return!

模拟数据库连接释放(联网操作)

场景: 模拟建立网络连接或数据库连接,必须确保最后关闭连接,防止资源泄露。

public class FinallyConnectionDemo {
    // 模拟一个连接
    static class Connection {
        boolean isClosed = false;
        void open() { System.out.println("连接已打开"); }
        void sendData(String data) { 
            // 模拟数据发送失败
            throw new RuntimeException("网络中断,发送失败!"); 
        }
        void close() { 
            isClosed = true;
            System.out.println("连接已关闭"); 
        }
    }
    public static void main(String[] args) {
        Connection conn = null;
        try {
            conn = new Connection();
            conn.open();
            // 发送数据,这里会抛异常
            conn.sendData("Hello");
        } catch (Exception e) {
            System.out.println("捕获到异常: " + e.getMessage());
            // 不能让程序崩溃,但连接必须关
        } finally {
            System.out.println("【finally】确保关闭连接...");
            if (conn != null && !conn.isClosed) {
                conn.close(); // 这里安全关闭
            }
        }
        System.out.println("程序优雅结束,连接已安全释放。");
    }
}

运行结果:

连接已打开
捕获到异常: 网络中断,发送失败!
【finally】确保关闭连接...
连接已关闭
程序优雅结束,连接已安全释放。

没有 finally 的后果: sendData 抛出异常,直接跳出 try 块,conn.close() 永远不会执行,导致连接泄露(最终可能导致系统资源耗尽)。


最佳实操原则(适合面试和写汇报)

  1. 写在一行? 不,try-catch-finally 是块结构,必须分行写,但你可以压行try (资源) { ... } 这是 try-with-resources,是finally的语法糖,适用于 AutoCloseable 的资源。
  2. 什么时候必须用 try-with-resources? 如果你操作的是 InputStreamOutputStreamConnectionStatementResultSet 这些资源,优先使用 try-with-resources(Java 7+),它能自动调用 close(),代码更简洁,且能正确处理隐式异常。
    // 用 try-with-resources 替代上面的案例一
    try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
        String line = reader.readLine();
        System.out.println(line);
    } catch (IOException e) {
        e.printStackTrace();
    } 
    // 不需要 finally 来 close(),自动完成
  3. 数据回滚或状态恢复: finally 也是理想的地方,比如一个操作完成了99%,突然失败了,你不能留下一个半成品状态。finally 可以帮你把一些“临时占位”恢复成原样。

总结一句话: 有借有还,才能再借不难;try 借资源,finally 负责还(释放/关闭)。

抱歉,评论功能暂时关闭!