概述
在Java中,final、finally和finalize前两个具是有不同含义和用途的关键字,而finalize 是Object类中的一个方法
final介绍
final 关键字用于修饰类、方法和变量。当类被声明为final时,表示它是最终类,不能被继承。当方法被声明为final时,表示它是最终方法,不能被子类重写。当变量被声明为final时,表示它是最终变量,即常量,一旦赋值后不能再次修改。
final 用法说明
- 当 final 修饰类时,此类不允许被继承,表示此类设计的很完美,不需要被修改和扩展。
- 当 final 修饰方法时,此方法不允许任何从此类继承的类来重写此方法,表示此方法提供的功能已经满足当前要求,不需要进行扩展。
- 当 final 修饰变量时,表示该变量一旦被初始化便不可以被修改。
- 当 final 修饰参数时,表示此参数在整个方法内不允许被修改。
final 用法示例
public final class MyClass { // 声明一个最终类
public final int MAX_VALUE = 100; // 声明一个最终变量
public final void printMessage() { // 声明一个最终方法
System.out.println("Hello, World!");
}
}
在这个示例中,MyClass 类被声明为最终类,意味着不能被继承。MAX_VALUE 变量被声明为最终变量,即常量,一旦赋值后不能再次修改。printMessage 方法被声明为最终方法,不能被子类重写。
finally介绍
finally关键字用于异常处理中的finally块。无论是否抛出异常,finally块中的代码总会被执行。通常用于释放资源或确保某些操作的必要执行,比如关闭数据库连接、关闭文件等。
在以下 4 种特殊情况下,finally块不会被执行:
- 在
finally语句块中发生了异常。 - 在前面的代码中用了
System.exit()退出程序。 - 程序所在的线程死亡。
- 关闭 CPU 。
finally 用法示例
public class FileHandler {
public void openFile(String fileName) {
try {
// 打开文件
// 进行文件操作
} catch (IOException e) {
// 处理异常
} finally {
// 无论是否发生异常,都会执行的代码块
// 释放资源或确保必要操作的执行
}
}
}
openFile 方法中,我们打开一个文件并进行一些操作。在 try-catch 块中,我们可以捕获可能发生的 IOException 异常并进行相应的处理。而在 finally 块中,我们可以放置一些资源释放的代码,无论是否发生异常,这些代码都会被执行。
finalize介绍
finalize方法是Object类中的一个方法,它在垃圾回收器对对象进行垃圾回收前会被调用。子类可以重写finalize方法来定义自己的垃圾回收行为,例如释放非Java堆内存资源。但是,由于finalize方法的触发时间是不确定的,不建议过多地依赖它来进行资源的释放和清理。
finalize用法示例
public class MyObject {
@Override
protected void finalize() throws Throwable {
try {
// 执行一些资源的释放或清理操作
} finally {
super.finalize();
}
}
}
在这个示例中,MyObject 类重写了 finalize 方法。在这个方法中,我们可以编写释放资源或清理操作的代码。需要注意的是,最后要调用 super.finalize() 方法以确保正确地进行垃圾回收的处理。
finalize 性能问题
finalize 除了执行“不稳定”之外,还有一定的性能问题。
因为 finalize 的执行是和垃圾收集关联在一起的,一旦实现了非空的 finalize 方法,就会导致相应对象回收呈现数量级上的变慢,有人专门做过 benchmark,大概是 40~50 倍的下降。
因为 finalize 被设计成在对象被垃圾收集前调用,这就意味着实现了 finalize 方法的对象是个“特殊公民”,JVM 要对它进行额外处理。finalize 本质上成为了快速回收的阻碍者,可能导致你的对象经过多个垃圾收集周期才能被回收。