final,finally,finalize的区别?

finalfinallyfinalize 是 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面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法