finally 关键字

概述

finally 关键字定义一个代码块,无论是否发生异常都会执行,通常用于资源清理。

语法格式

try {
    // 可能抛出异常的代码
} catch (Exception e) {
    // 异常处理
} finally {
    // 总是执行的代码
}

基本用法

public class FinallyExample {
    public static void main(String[] args) {
        System.out.println("开始执行");

        try {
            System.out.println("try块执行");
            int result = 10 / 0; // 抛出异常
            System.out.println("这行不会执行");
        } catch (ArithmeticException e) {
            System.out.println("catch块执行: " + e.getMessage());
        } finally {
            System.out.println("finally块总是执行");
        }

        System.out.println("程序继续执行");
    }
}

资源清理

import java.io.*;

public class ResourceCleanupExample {
    public static void readFile(String filename) {
        FileInputStream fis = null;
        BufferedReader reader = null;

        try {
            fis = new FileInputStream(filename);
            reader = new BufferedReader(new InputStreamReader(fis));

            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

        } catch (FileNotFoundException e) {
            System.out.println("文件未找到: " + e.getMessage());
        } catch (IOException e) {
            System.out.println("读取错误: " + e.getMessage());
        } finally {
            // 清理资源 - 无论是否异常都会执行
            System.out.println("清理资源...");

            if (reader != null) {
                try {
                    reader.close();
                    System.out.println("关闭BufferedReader");
                } catch (IOException e) {
                    System.out.println("关闭BufferedReader失败");
                }
            }

            if (fis != null) {
                try {
                    fis.close();
                    System.out.println("关闭FileInputStream");
                } catch (IOException e) {
                    System.out.println("关闭FileInputStream失败");
                }
            }
        }
    }

    public static void main(String[] args) {
        readFile("test.txt");
        readFile("nonexistent.txt");
    }
}

finally执行时机

public class FinallyExecutionExample {

    public static int testReturn() {
        try {
            System.out.println("try块中的return");
            return 1;
        } catch (Exception e) {
            System.out.println("catch块中的return");
            return 2;
        } finally {
            System.out.println("finally块执行");
            // 注意:finally中的return会覆盖try/catch中的return
            // return 3; // 如果取消注释,方法将返回3
        }
    }

    public static int testFinallyReturn() {
        try {
            return 1;
        } finally {
            return 2; // 这个返回值会覆盖try中的返回值
        }
    }

    public static int testException() {
        try {
            System.out.println("抛出异常");
            throw new RuntimeException("测试异常");
        } catch (RuntimeException e) {
            System.out.println("捕获异常: " + e.getMessage());
            return 1;
        } finally {
            System.out.println("finally块在return之前执行");
        }
    }

    public static void main(String[] args) {
        System.out.println("=== 测试return ===");
        int result1 = testReturn();
        System.out.println("返回值: " + result1);

        System.out.println("\n=== 测试finally中的return ===");
        int result2 = testFinallyReturn();
        System.out.println("返回值: " + result2);

        System.out.println("\n=== 测试异常处理 ===");
        int result3 = testException();
        System.out.println("返回值: " + result3);
    }
}

finally与变量修改

import java.util.ArrayList;
import java.util.List;

public class FinallyVariableExample {

    public static int testPrimitiveVariable() {
        int value = 10;
        try {
            value = 20;
            return value;
        } finally {
            value = 30; // 这不会影响返回值
            System.out.println("finally中value = " + value);
        }
    }

    public static List<String> testObjectVariable() {
        List<String> list = new ArrayList<>();
        try {
            list.add("try");
            return list;
        } finally {
            list.add("finally"); // 这会影响返回的对象
            System.out.println("finally中list = " + list);
        }
    }

    public static StringBuilder testStringBuilder() {
        StringBuilder sb = new StringBuilder("initial");
        try {
            sb.append("-try");
            return sb;
        } finally {
            sb.append("-finally"); // 这会影响返回的对象
            System.out.println("finally中sb = " + sb);
        }
    }

    public static void main(String[] args) {
        System.out.println("=== 基本类型变量 ===");
        int result1 = testPrimitiveVariable();
        System.out.println("返回值: " + result1);

        System.out.println("\n=== 对象变量 ===");
        List<String> result2 = testObjectVariable();
        System.out.println("返回值: " + result2);

        System.out.println("\n=== StringBuilder ===");
        StringBuilder result3 = testStringBuilder();
        System.out.println("返回值: " + result3);
    }
}

finally的特殊情况

public class FinallySpecialCases {

    // System.exit()会阻止finally执行
    public static void testSystemExit() {
        try {
            System.out.println("try块执行");
            System.exit(0); // 程序退出,finally不会执行
        } finally {
            System.out.println("这行不会执行");
        }
    }

    // 虚拟机崩溃时finally不会执行
    public static void testVMCrash() {
        try {
            System.out.println("try块执行");
            // 模拟VM崩溃(实际开发中不要这样做)
            Runtime.getRuntime().halt(1);
        } finally {
            System.out.println("这行不会执行");
        }
    }

    // 无限循环会阻止finally执行
    public static void testInfiniteLoop() {
        try {
            System.out.println("进入无限循环");
            while (true) {
                // 无限循环
            }
        } finally {
            System.out.println("这行不会执行");
        }
    }

    // 正常情况下finally总是执行
    public static void testNormalFinally() {
        try {
            System.out.println("try块执行");
            throw new RuntimeException("测试异常");
        } catch (RuntimeException e) {
            System.out.println("catch块执行");
            throw new RuntimeException("重新抛出");
        } finally {
            System.out.println("finally块执行");
        }
    }

    public static void main(String[] args) {
        System.out.println("=== 正常finally ===");
        try {
            testNormalFinally();
        } catch (Exception e) {
            System.out.println("最外层捕获: " + e.getMessage());
        }

        // 注意:以下调用会导致程序退出
        // testSystemExit();
        // testVMCrash();
        // testInfiniteLoop();
    }
}

try-with-resources与finally

import java.io.*;

public class TryWithResourcesExample {

    // 实现AutoCloseable接口的自定义资源
    static class CustomResource implements AutoCloseable {
        private String name;

        public CustomResource(String name) {
            this.name = name;
            System.out.println("创建资源: " + name);
        }

        public void doSomething() {
            System.out.println("使用资源: " + name);
        }

        @Override
        public void close() {
            System.out.println("关闭资源: " + name);
        }
    }

    // try-with-resources + finally
    public static void testTryWithResourcesFinally() {
        try (CustomResource resource1 = new CustomResource("资源1");
             CustomResource resource2 = new CustomResource("资源2")) {

            resource1.doSomething();
            resource2.doSomething();

            // 模拟异常
            throw new RuntimeException("测试异常");

        } catch (Exception e) {
            System.out.println("捕获异常: " + e.getMessage());
        } finally {
            System.out.println("finally块执行");
        }
        // 资源自动关闭发生在finally之前
    }

    public static void main(String[] args) {
        testTryWithResourcesFinally();
    }
}

最佳实践

public class FinallyBestPractices {

    // 好的做法:只在finally中进行清理操作
    public static void goodPractice() {
        Resource resource = null;
        try {
            resource = acquireResource();
            useResource(resource);
        } catch (Exception e) {
            handleException(e);
        } finally {
            if (resource != null) {
                releaseResource(resource);
            }
        }
    }

    // 避免在finally中抛出异常
    public static void avoidExceptionInFinally() {
        try {
            // 主要逻辑
        } catch (Exception e) {
            // 异常处理
        } finally {
            try {
                // 清理操作
                performCleanup();
            } catch (Exception e) {
                // 记录日志,但不要重新抛出
                System.err.println("清理时发生错误: " + e.getMessage());
            }
        }
    }

    // 推荐:使用try-with-resources
    public static void recommendedApproach() {
        try (Resource resource = acquireResource()) {
            useResource(resource);
        } catch (Exception e) {
            handleException(e);
        }
        // 资源自动关闭,无需finally
    }

    // 模拟方法
    private static Resource acquireResource() { return new Resource(); }
    private static void useResource(Resource r) { }
    private static void releaseResource(Resource r) { }
    private static void handleException(Exception e) { }
    private static void performCleanup() { }

    static class Resource implements AutoCloseable {
        @Override
        public void close() { }
    }
}

finally关键字确保重要的清理代码总是执行,是编写健壮程序的重要工具。

powered by Gitbook© 2025 编外计划 | 最后修改: 2025-07-28 16:25:54

results matching ""

    No results matching ""