准确区分 final(关键字)、finally(异常处理块)和 finalize()(对象清理方法)三者的用途
掌握 final 在变量、方法和类上的不同语义
理解 finally 块的执行机制及其在资源管理中的作用
了解 finalize() 方法的局限性及为何在现代 Java 中已被弃用
能够在实际开发中正确、安全地使用这三种机制
final 关键字final 是 Java 中用于限制修改的关键字,可应用于变量、方法和类。
final 变量:常量声明一旦被初始化,final 变量的值不能被更改。
public class FinalVariableExample {
public static void main(String[] args) {
int a = 5; // 普通变量,可修改
final int b = 10; // final 变量,不可修改
a++; // 合法
// b++; // 编译错误!Cannot assign a value to final variable 'b'
System.out.println("a = " + a + ", b = " + b);
}
}注意:
final局部变量必须在声明时或之后初始化一次。对于引用类型(如对象),
final仅保证引用不可变,但对象内部状态仍可修改。
final StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 合法!对象内容可变
// sb = new StringBuilder(); // 非法!引用不可重新赋值final 方法:禁止重写被 final 修饰的方法不能被子类重写(override)。
class Parent {
final void display() {
System.out.println("这是 final 方法");
}
}
class Child extends Parent {
// void display() { } // 编译错误!Cannot override final method
}用途:防止关键方法被意外或恶意覆盖,保障类的行为一致性。
final 类:禁止继承被 final 修饰的类不能被继承。
final class UtilityClass {
public static void helper() {
System.out.println("工具方法");
}
}
// class SubClass extends UtilityClass { } // 编译错误!Cannot inherit from final class典型例子:
String、Math、Integer等核心类均为final,确保安全性和不可变性。
finally 块finally 是异常处理机制的一部分,用于定义无论是否发生异常都必须执行的代码,常用于资源释放。
基本语法
try {
// 可能抛出异常的代码
} catch (Exception e) {
// 异常处理
} finally {
// 总是执行的清理代码
}示例:文件操作中的资源关闭
import java.io.*;
public class FinallyExample {
public static void main(String[] args) {
FileReader reader = null;
try {
reader = new FileReader("example.txt");
System.out.println("文件读取中...");
int data = reader.read(); // 可能抛出 IOException
} catch (IOException e) {
System.out.println("读取文件失败: " + e.getMessage());
} finally {
if (reader != null) {
try {
reader.close(); // 确保文件流关闭
System.out.println("文件流已关闭");
} catch (IOException e) {
System.out.println("关闭文件失败");
}
}
}
}
}执行保证:即使
try或catch中有return、break或异常,finally仍会执行(除非调用System.exit())。
特殊情况:finally 中的 return
public static int getValue() {
try {
return 1;
} finally {
return 2; // 这会覆盖 try 中的 return!
}
}警告:在
finally中使用return会掩盖异常或原始返回值,应避免。
finalize() 方法对象销毁前的清理(已弃用)
finalize() 是 Object 类中的一个方法,在对象被垃圾回收器(GC)回收之前由 JVM 调用,用于执行清理操作。
基本用法(仅作理解,不推荐使用)
public class FinalizeExample {
@Override
protected void finalize() throws Throwable {
System.out.println("对象即将被回收,执行清理...");
super.finalize(); // 建议调用父类 finalize
}
public static void main(String[] args) {
FinalizeExample obj = new FinalizeExample();
obj = null; // 对象变为不可达
System.gc(); // 建议 JVM 执行垃圾回收(不保证立即执行)
try {
Thread.sleep(1000); // 等待 GC
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("程序结束");
}
}为什么 finalize() 被弃用?
从 Java 9 开始,finalize() 被标记为 @Deprecated,原因包括:
替代方案
推荐使用以下方式替代 finalize():
try-with-resources(自动关闭资源):
try (FileInputStream fis = new FileInputStream("file.txt")) {
// 使用资源
} // 自动调用 close()显式清理方法(如 close()、dispose()):
class Resource implements AutoCloseable {
public void close() {
// 清理逻辑
}
}Cleaner 机制(Java 9+):
private static final Cleaner cleaner = Cleaner.create();
private final Cleaner.Cleanable cleanable;
public MyResource() {
cleanable = cleaner.register(this, new CleanupAction());
}final 是实现不可变性和封装安全的重要工具。
finally 是异常处理中确保资源释放的关键机制,但应避免在其中使用 return。
finalize() 不应在现代 Java 应用中使用,应改用 try-with-resources、AutoCloseable 或 Cleaner。
三者名称相似,但用途完全不同,切勿混淆。
如果一个 final 变量是对象引用,能否修改该对象的内部状态?请举例说明。
在 try 块中执行 System.exit(0),finally 块还会执行吗?为什么?
为什么 Java 设计者决定弃用 finalize()?你认为这种设计对开发者有何影响?