final、finally 和 finalize 是 Java 中具有不同用途的三个关键字或方法。
final
final: 用于修饰类、方法和变量,表示它们不能被继承、重写或修改。
当一个类被声明为 final 时,它不能被继承:
public final class FinalClass {
// 类内容
}
// public class SubClass extends FinalClass { // 编译错误,不能继承 final 类
// // 子类内容
// }
当一个方法被声明为 final 时,它不能被子类重写:
public class BaseClass {
public final void display() {
System.out.println("This is a final method.");
}
}
public class DerivedClass extends BaseClass {
// public void display() { // 编译错误,不能重写 final 方法
// System.out.println("Trying to override.");
// }
}
当一个变量被声明为 final 时,它的值在初始化之后不能被改变:
public class MyClass {
public static final int MY_CONSTANT = 10;
}
finally
finally: 用于异常处理中的代码块,无论是否发生异常,都会执行清理代码。
try {
// 可能产生异常的代码
} catch (Exception e) {
// 处理异常
} finally {
// 清理代码,无论是否发生异常都会执行
}
我们可以使用 try-finally 、或者try-catch-finally 来进行类似关闭 JDBC 连接、保证 unlock 锁等动作。
但是,以下是几个导致 finally 块不会被执行,需要注意:
1、JVM 非正常退出
public class FinallyExample {
public static void main(String[] args) {
try {
System.out.println("Try block");
System.exit(0); // 强制退出
} finally {
System.out.println("Finally block");
}
}
}
如果程序调用了 System.exit() 方法导致 JVM 强制退出,finally 块将不会被执行。
2、无限循环
public class FinallyExample {
public static void main(String[] args) {
try {
while (true) {
// 无限循环
}
} finally {
System.out.println("Finally block");
}
}
}
如果 finally 块所在的代码陷入了无限循环或者死锁状态,导致程序无法正常终止,finally 块也不会被执行。
3、OOM(Out Of Memory)错误
import java.util.ArrayList;
import java.util.List;
public class FinallyExample {
public static void main(String[] args) {
try {
List<byte[]> list = new ArrayList<>();
while (true) {
list.add(new byte[1000000]); // 内存耗尽
}
} finally {
System.out.println("Finally block");
}
}
}
try 块导致内存耗尽,抛出 OutOfMemoryError 错误,导致程序异常终止,finally 块也不会被执行。
finalize
finalize: 用于对象被垃圾回收之前的清理操作。
public class MyClass {
@Override
protected void finalize() throws Throwable {
try {
// 资源清理代码
} finally {
super.finalize();
}
}
}
finalize 方法已经过时,不推荐使用。
因为,finalize 的执行是和垃圾收集关联在一起的,finalize 被设计成在对象被垃圾收集前调用。
这就意味着,finalize 本质上成为了快速回收的阻碍,可能导致你的对象经过多个垃圾收集周期才能被回收。
所以,现在推荐使用其他资源管理方式,如 try-with-resources 语句或显式的资源关闭方法:
try-with-resources 能自动关闭实现了: AutoCloseable、 或 Closeable 接口的资源,确保资源及时释放。
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
// 使用资源
} catch (IOException e) {
e.printStackTrace();
}
这就是try-with-resource 结构的用法,BufferedReader 类型变量就在try关键字后面的括号中声明,当try语句块运行结束时,BufferedReader 会被自动关闭。
这是因为BufferedReader 实现了java中的java.lang.AutoCloseable接口,所有实现了这个接口的类都可以在try-with-resources结构中使用。
mikechen睿哥
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。