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年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》