在Java中,final、finally 和 finalize 是完全不同的三个概念,主要区别如下:
1. final(关键字)
作用:用于声明不可变的实体
- 修饰变量:变量一旦初始化就不能被修改(基本类型值不能变,引用类型引用不能变)
- 修饰方法:方法不能被子类重写(override)
- 修饰类:类不能被继承
// 1. final变量
final int MAX_VALUE = 100; // 常量
final List<String> list = new ArrayList<>(); // 引用不可变,但list内容可改
// 2. final方法
class Parent {
public final void show() { // 子类不能重写此方法
System.out.println("final method");
}
}
// 3. final类
final class FinalClass { // 不能被继承
// ...
}
2. finally(代码块)
作用:异常处理的一部分,确保代码无论是否发生异常都会执行
- 用于资源清理(关闭文件、数据库连接等)
- 通常与 try-catch 一起使用
- 除非程序退出(System.exit()),否则 finally 块一定会执行
try {
// 可能抛出异常的代码
FileInputStream fis = new FileInputStream("file.txt");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 无论是否发生异常都会执行
// 关闭资源
if (fis != null) {
fis.close();
}
}
3. finalize(方法)
作用:Object 类的方法,垃圾回收前被调用
- 用于对象被GC回收前的清理工作
- 不建议使用,因为执行时机不确定
- 从 Java 9 开始已被标记为过时(deprecated)
class MyClass {
// 不建议使用的方法
@Override
protected void finalize() throws Throwable {
try {
// 清理资源
} finally {
super.finalize();
}
}
}
对比总结
| 特性 | final | finally | finalize |
|---|---|---|---|
| 类型 | 关键字 | 代码块/关键字 | 方法 |
| 用途 | 定义不可变性 | 异常处理的清理 | 对象回收前的清理 |
| 上下文 | 变量、方法、类 | 异常处理(try-catch) | 垃圾回收机制 |
| 执行时机 | 编译时/运行时 | 异常处理后一定执行 | GC时不确定执行 |
| 推荐使用 | ✅ 常用 | ✅ 常用 | ❌ 已过时 |
使用建议
- final:用于设计不可变类、常量、防止继承或重写
- finally:必须用于资源清理,或确保某些操作一定执行
- finalize:避免使用,改用 try-with-resources 或 Cleaner 机制
现代替代方案
对于资源清理,推荐使用 try-with-resources(Java 7+):
// 自动关闭资源,无需finally手动关闭
try (FileInputStream fis = new FileInputStream("file.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis))) {
// 使用资源
} catch (IOException e) {
e.printStackTrace();
}
这三个概念名称相似但功能完全不同,理解它们的区别是Java基础的重要部分。