finalize() 方法介绍

1、什么是 finalize() 方法?

finalize() 方法是 Java 中 java.lang.Object 类提供的一个方法,是JVM回收该垃圾象内存之前调用的方法,其声明如下:

java 复制代码
protected void finalize() throws Throwable
  • 它是 ​Object 类的一个 protected受保护的方法,所有 Java 类都默认继承了这个方法。
  • finalize() 方法是在垃圾回收器(Garbage Collector, GC)准备回收某个对象所占用的内存之前,由 JVM 自动调用的。​(垃圾回收之前自动调用)
  • 可以重写该方法,用于在对象被销毁前执行一些清理工作​(如关闭资源、释放外部链接等)。
  • 方法可以抛出 ​Throwable​(包括 Exception 和 Error),但一般不建议抛出异常
  • 默认的 Object.finalize() 是一个空实现,什么都不做

2、finalize() 的基本工作原理

当一个对象没有任何引用指向它​(成为垃圾 ),垃圾回收器会在某个不确定的时间将其标记为可回收。

在真正回收该对象的内存之前,​JVM 会调用该对象的 finalize() 方法(如果该对象重写了此方法)​

执行顺序:

1、对象成为垃圾

2、垃圾回收器发现该对象可被回收

3、在回收该对象内存之前,JVM 会调用该对象的 finalize() 方法(如果存在)​。

4、垃圾回收器在某个时间点真正回收该对象占用的内存。

⚠️ 注意:调用 finalize() 并不意味着对象一定会被回收! 甚至也有可能通过 finalize() 方法处理来"复活"对象(极为罕见且不推荐)。

**3、**重写 finalize() 方法(代码示例)

java 复制代码
public class User{
    private String name;

    public User(String name) {
        this.name = name;
        System.out.println(name + " 对象已创建");
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            System.out.println(name + " 对象即将被垃圾回收,finalize() 被调用!");
            // 可以在这里执行一些资源释放逻辑,但不保证一定会执行
        } finally {
            super.finalize(); // 调用父类的 finalize(一般无实际意义)
        }
    }
}

测试代码

java 复制代码
public class Test {
    public static void main(String[] args) {
        new User("TestObject");
        // 提醒 JVM 进行垃圾回收(但不保证马上执行!)
        System.gc();
        // 提醒 JVM 进行 finalize 线程的处理
        System.runFinalization();

        System.out.println("程序结束");
    }
}

输出结果:

html 复制代码
TestObject 对象已创建
TestObject 对象即将被垃圾回收,finalize() 被调用!
程序结束

注意:输出结果可能不保证顺序,也不保证 finalize 一定会被调用!

4、finalize() 的特点

  1. ​调用时机不确定​

    • finalize() 的调用是由 垃圾回收器控制的,无法控制它何时执行,甚至不保证一定会执行。
    • 即使调用了 System.gc()System.runFinalization(),也只是建议​ JVM 执行 GC,不保证效果。
  2. ​不保证一定会被执行​

    • 如果 JVM 在对象成为垃圾后直接回收内存,而没有调用 finalize(),那么该方法就不会被执行。
    • 在程序退出时,某些未被回收的对象的 finalize() 也可能根本不会被调用。
  3. ​性能开销大​

    • 使用 finalize() 会 ​增加垃圾回收的负担,JVM 需要额外维护一个 Finalizer 队列与线程来处理它。
    • 导致 ​GC 变慢,对象回收延迟。
  4. ​不要依赖它释放关键资源​

    • 关闭文件、数据库连接、网络连接等,绝对不要依赖 finalize() 来释放资源,因为它可能永远不会被调用!

5、做资源清理时推荐的方式

1. ​使用 try-with-resources(Java 7+ 以后)​

代码示例:

java 复制代码
try (FileInputStream fis = new FileInputStream("test.txt")) {
    // 资源处理
} catch (IOException e) {
    e.printStackTrace();
}
// fis 会自动调用 close(),无需 finalize!

​2.手动在 finally 块中调用 close()​

java 复制代码
FileInputStream fis = null;
try {
    fis = new FileInputStream("test.txt");
    // 资源处理
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (fis != null) {
        try {
            fis.close(); // 关闭
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

做资源清理时避免使用 finalize(),在 Java 9 开始,finalize() 方法已被标记为 @Deprecated(since="9"),表示不推荐使用,未来可能会被移除。Java 官方文档明确指出:不应依赖 finalize() 进行必要的清理工作。

6、补充:finalize() 的极端情况:对象"复活"

java 复制代码
@Override
protected void finalize() throws Throwable {
    System.out.println("finalize() 被调用,尝试复活对象");
    SomeClass.saved = this; // 不要这样做!
}

在极少数情况下,在 finalize() 方法中将 this 赋值给某个静态变量,可能让对象"复活"​​(即暂时不被回收),但这种做法极其不推荐,会导致内存泄漏和不可预测的行为。

相关推荐
HappyAcmen4 小时前
【自动化实战】Python操作Excel/WORD/PDF:openpyxl与docx库详解
python·自动化·excel
q567315234 小时前
无需Python:Shell脚本如何成为你的自动化爬虫引擎?
开发语言·爬虫·python·自动化·scala
aiden:)4 小时前
App UI 自动化环境搭建指南
运维·python·ui·appium·自动化
hqyjzsb4 小时前
2025职场进阶:B端产品经理必备的计算机专业技能精要
大数据·开发语言·人工智能·产品经理·编程语言·caie
一杯敬朝阳 一杯敬月光6 小时前
记录下chatgpt的openai 开发过程
python·chatgpt·flask
云天徽上6 小时前
【数据可视化-106】华为2025上半年财报分析:用Python和Pyecharts打造炫酷可视化大屏
开发语言·python·华为·信息可视化·数据分析·pyecharts
极客小张7 小时前
【项目思路】基于STM32+ZigBee的智能家居--浴室场景设计
c语言·python·stm32·智能家居·课程设计·项目设计·企业项目
墩墩分墩9 小时前
【Go语言入门教程】 Go语言的起源与技术特点:从诞生到现代编程利器(一)
开发语言·后端·golang·go
CHANG_THE_WORLD9 小时前
并发编程指南 同步操作与强制排序
开发语言·c++·算法