详解Java的finalize()方法:在对象被垃圾回收器回收之前调用

  • Post category:Java

以下是Java中finalize()方法的详细讲解:

finalize()方法是什么?

finalize()方法是Object类中定义的一个方法,用于在对象被垃圾回收器回收时调用。子类可以覆盖此方法以在对象变为不可达时执行任意清理操作,例如,关闭已打开的文件或套接字。

finalize()方法的执行时机

Java垃圾回收器会定期检查堆上的对象,并确定哪些对象是不再被引用的,以便释放它们占用的内存。 在垃圾回收过程中,当确定对象不再被引用时,将调用finalize()方法。 确切的时间是由垃圾回收器的实现决定的,因此执行finalize()方法的时间是不确定的。

以下是一个重写了finalize()方法的示例代码:

public class MyClass {
    private SomeResource resource;

    // 构造函数
    public MyClass() {
        resource = new SomeResource();
    }

    // 重写finalize()方法
    @Override
    protected void finalize() throws Throwable {
        try {
            resource.close();
        } finally {
            super.finalize();
        }
    }
}

在这个示例代码中,MyClass类包含一个资源对象resource,并且在构造函数中对其进行初始化。我们重写了finalize()方法,以确保在MyClass对象被垃圾回收器回收之前,会关闭resource对象。

注意事项

finalize()方法不应该用于释放内存

虽然可以在finalize()方法中关闭文件和套接字等资源,但是它不是释放内存的可靠方式。因为垃圾回收机制本身就是用于释放内存的,如果Java虚拟机未执行finalize方法,那么系统里就会有未关闭的文件和套接字。因此,finalize()方法应当被视为一个通知机制,告诉程序应当执行一些清理动作。

finalize()方法只会被执行一次

在Java中,当一个对象被标记为“不可达”时,垃圾回收器只会对其调用一次finalize()方法。之后,对象就会被视为死亡对象,之后就不会再次执行finalize()方法。因此,如果需要在多次对象回收前做一些清理动作,应当显式调用相关方法,而不是依靠finalize()方法。

示例代码

以下是一个Person类的示例代码,实现了finalize()方法:

public class Person {
    private String name;
    private int age;

    // 构造函数
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 重写finalize()方法
    @Override
    protected void finalize() throws Throwable {
        try {
            System.out.println(name + "对象被回收了");
        } finally {
            super.finalize();
        }
    }

    // 主函数
    public static void main(String[] args) {
        Person p1 = new Person("张三", 20);
        p1 = null;
        Person p2 = new Person("李四", 30);
        p2 = null;

        // 强制垃圾回收
        System.gc();
    }
}

在这个示例代码中,我们创建了两个Person对象,并将其设置为null。接着,我们强制执行垃圾回收(System.gc()方法),此时,会自动执行Person对象的finalize()方法。

输出结果如下:

张三对象被回收了
李四对象被回收了

可以看到,当Person对象被垃圾回收器回收时,会自动调用finalize()方法,输出一条提示信息。