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关键字确保重要的清理代码总是执行,是编写健壮程序的重要工具。