final、finally、finalize 的区别
参考回答**
在Java中,final
、finally
和 finalize
是三个完全不同的概念,尽管名字相似,但它们分别用于变量、代码块和对象生命周期,其含义和使用场景也各不相同:
final
:一个关键字,用于修饰类、方法和变量,表示不能被修改或继承。finally
:一个代码块,常与try-catch
一起使用,表示无论是否发生异常,都一定会执行的代码。finalize
:一个方法,用于垃圾回收时对对象进行清理操作,但很少使用。
详细讲解与拓展
1. final
final
是一个修饰符,可以用来修饰类、方法和变量,含义如下:
- 修饰类:被修饰的类不能被继承。
- 修饰方法:被修饰的方法不能被子类重写。
- 修饰变量:被修饰的变量是常量,初始化后值不能被修改。
例子:
// 修饰类
final class Animal {
// ...
}
// class Dog extends Animal {} // 编译错误,因为Animal是final类
// 修饰方法
class Animal {
final void sound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
// void sound() {} // 编译错误,无法重写final方法
}
// 修饰变量
class Example {
public static void main(String[] args) {
final int a = 10;
// a = 20; // 编译错误,final变量的值不能被修改
}
}
注意:
-
final
修饰引用类型时,引用地址不能被修改,但引用指向的对象内容是可以修改的。
final List<String> list = new ArrayList<>(); list.add("Hello"); // 允许 // list = new ArrayList<>(); // 编译错误
2. finally
finally
是一个代码块,用于保证无论try
代码块是否抛出异常,某些必要的清理工作(如释放资源、关闭文件)一定会执行。
特点:
finally
代码块与try-catch
配合使用。- 即使
try
中有return
语句,finally
仍会执行。 - 唯一不会执行
finally
的情况是:程序在try
或catch
中使用了System.exit(0)
终止程序。
例子:
public class Example {
public static void main(String[] args) {
try {
System.out.println("Inside try block");
int result = 10 / 0; // 触发异常
} catch (ArithmeticException e) {
System.out.println("Exception caught: " + e.getMessage());
} finally {
System.out.println("Finally block executed");
}
}
}
输出:
Inside try block
Exception caught: / by zero
Finally block executed
finally
中的代码始终会执行:
public class Example {
public static void main(String[] args) {
System.out.println(testFinally());
}
static int testFinally() {
try {
return 1; // 尝试返回
} finally {
System.out.println("Finally block executed");
return 2; // 最终返回值被覆盖为2
}
}
}
输出:
Finally block executed
2
常见用途:
- 用于关闭资源,如文件、数据库连接等:
try { BufferedReader reader = new BufferedReader(new FileReader("file.txt")); // 读取文件操作 } catch (IOException e) { e.printStackTrace(); } finally { reader.close(); // 无论如何都要关闭文件 }
3. finalize
finalize
是Object
类的一个方法,它在垃圾回收器(GC)回收对象之前被调用,用于进行资源回收或清理工作。
特点:
- 每个类都可以重写
finalize
方法,用于释放对象占用的资源,比如文件句柄、网络连接等。 - 但不推荐使用,因为Java的垃圾回收机制已经能很好地管理资源,
finalize
增加了GC的开销,效率较低,且行为不确定(调用时间不确定)。
例子:
class Example {
@Override
protected void finalize() throws Throwable {
System.out.println("Finalize method called");
}
public static void main(String[] args) {
Example obj = new Example();
obj = null; // 使对象变成垃圾
System.gc(); // 提示JVM进行垃圾回收
System.out.println("End of program");
}
}
输出:
End of program
Finalize method called
注意:
System.gc()
只是建议JVM进行垃圾回收,实际是否执行finalize
方法取决于JVM实现。finalize
方法已被逐步废弃,从Java 9开始被标记为deprecated
,Java 14中被彻底移除。
替代方案: 对于资源清理任务,推荐使用try-with-resources
语句或显式的关闭方法。
总结对比
特性 | final |
finally |
finalize |
---|---|---|---|
用法 | 修饰类、方法或变量 | 一个代码块,用于资源清理或最终执行代码 | 一个方法,用于对象被垃圾回收前的清理工作 |
位置 | 用于类定义、方法定义、变量定义 | 用于try-catch 块 |
定义在Object 类中,可被子类重写 |
执行时机 | 编译时生效 | 程序运行时,try-catch 块结束后执行 |
垃圾回收时被调用,时间不确定 |
功能 | 防止修改、重写、继承 | 保证必要代码一定会执行 | 资源回收或清理工作,但不推荐使用 |
推荐程度 | 推荐,广泛使用 | 推荐,特别适合资源清理操作 | 不推荐,从Java 9开始被废弃,建议使用try-with-resources |
总结
final
:- 防止变量值被修改(常量)。
- 防止方法被重写。
- 防止类被继承。
finally
:- 用于资源清理或释放,无论是否发生异常都会执行。
finalize
:- 用于垃圾回收前的清理工作,但不推荐使用,取而代之的是
try-with-resources
或显式关闭资源方法。
- 用于垃圾回收前的清理工作,但不推荐使用,取而代之的是