Java_5.析构函数

在面向对象编程中,构造函数和析构函数是用来创建和销毁对象的特殊方法。在Java中,构造函数和析构函数被称为构造器和终结器,分别用于对象的初始化和销毁。

PS:构造函数在Java_2介绍过  这里就不介绍了。

构造器是一种特殊的方法,用于在对象创建时初始化该对象的状态。在Java中,构造器的名称必须与类名相同,它没有返回类型,也不需要显示声明返回类型。在创建对象时,会自动调用与该类名称相同的构造器,并在构造器中执行必要的初始化操作。如果一个类没有定义构造器,则会默认提供一个无参构造器。如果需要定义有参构造器,需要在类中显式声明。

 

析构函数则是一种在对象销毁时自动被调用的特殊方法。在Java中,由于Java具有自动垃圾回收机制,因此不需要显式地调用析构函数来销毁对象。当对象不再被引用时,Java虚拟机会自动回收该对象所占用的内存空间。

需要注意的是,在Java中并没有直接的析构函数。相反,Java提供了finalize()方法来实现类似于析构函数的功能。在Java中,如果定义了finalize()方法,当对象被垃圾回收时,该方法会自动被调用。

finalize()方法是一个受保护的方法,它在Object类中定义,子类可以重写该方法以实现自己的清理逻辑。finalize()方法的声明如下:

需要注意的是,finalize()方法只在垃圾回收器进行对象回收之前被调用一次,因此不能保证该方法被及时执行或者执行一次。此外,由于Java虚拟机的垃圾回收机制是不确定的,所以应该尽量避免在finalize()方法中编写过多的代码,以免影响程序的性能。

在Java 9中,finalize()方法已经被弃用,取而代之的是Cleaner类,可以通过Cleaner类中的clean()方法实现类似于finalize()方法的清理逻辑。

Cleaner类是Java 9引入的一个新类,用于替代Java 8中已经废弃的finalize()方法。Cleaner类的主要作用是在Java对象不再被引用时执行一些清理操作,从而避免了垃圾回收机制的不确定性。

Cleaner类中有一个clean()方法,它的作用是执行清理操作。当Java对象不再被引用时,垃圾回收器会将它放入一个待清理队列中。然后,在某个时刻,Cleaner线程会扫描这个队列,执行队列中所有对象的clean()方法。

在Cleaner类中,使用了一个“幽灵引用”(PhantomReference)来实现对象的清理。幽灵引用是一种特殊的引用,它的作用是在对象被垃圾回收器回收时得到通知,但是在这个时刻之前,无法通过幽灵引用访问到这个对象。当一个对象被垃圾回收器回收时,它的幽灵引用会被放入待清理队列中,然后在Cleaner线程中执行清理操作。

假设我们在编写一个处理文件的程序,我们需要在文件处理完毕后关闭文件句柄。但是由于一些原因(例如程序异常终止),可能会导致文件句柄没有被关闭,从而导致资源泄漏。为了解决这个问题,我们可以使用Cleaner类来注册一个回调函数,在Cleaner对象被回收时自动执行关闭文件句柄的操作。

举一个复杂的例子:(注释给了,看不懂没关系,就是要多看例子才会写)

import java.io.File; //引入File类,用于操作文件。
import java.io.FileInputStream; //引入FileInputStream类,用于读取文件。
import java.io.IOException; //引入IOException异常,用于处理文件读取异常。
import java.lang.ref.Cleaner; //引入Cleaner类,用于管理和执行清理操作。

public class FileHandler implements Runnable { //定义FileHandler类,实现Runnable接口,用于处理文件相关逻辑。
    private final File file; //定义file变量,表示要处理的文件。
    private final FileInputStream fis; //定义fis变量,表示要读取的文件流。
    private final Cleaner cleaner; //定义cleaner变量,用于管理和执行清理操作。

    public FileHandler(File file) throws IOException { //定义FileHandler的构造函数,传入要处理的文件,并抛出IOException异常。
        this.file = file; //将传入的文件赋值给file变量。
        fis = new FileInputStream(file); //创建一个新的FileInputStream对象,用于用于读取文件。
        cleaner = Cleaner.create(); //创建一个Cleaner对象,用于管理和执行清理操作。
        cleaner.register(this, new CloseHandler(fis));
        //册一个清理操作,当FileHandler对象被回收时,会自动调用CloseHandler的run()方法,关闭fis文件流。
    }

    @Override //重写run()方法。
    public void run() { //run()方法实现,用于处理文件相关逻辑。
        // TODO: 处理文件逻辑
    }

    private static class CloseHandler implements Runnable {
        //定义CloseHandler内部类,实现Runnable接口,用于关闭文件流。
        private final FileInputStream fis; //定义fis变量,表示要关闭的文件流.

        public CloseHandler(FileInputStream fis) {//定义CloseHandler的构造函数,传入要关闭的文件流。
            this.fis = fis; //将传入的文件流赋值给fis变量
        }

        @Override //重写run()方法
        public void run() { //run()方法实现,用于关闭文件流。
            try { //开始try块。
                fis.close(); //关闭文件流。
                System.out.println("File " + fis.getFD() + " has been closed"); //输出文件流已经被关闭的消息。
            } catch (IOException e) { //捕获IOException异常。
                try { //开始try块。
                    System.err.println("Failed to close file " + fis.getFD()); //输出文件关闭失败的消息。
                } catch (IOException ex) { //捕获IOException异常。
                    throw new RuntimeException(ex); //抛出异常
                }
            } //try-catch块结束
        } //run()方法结束。
    } //CloseHandler内部类结束。
} //FileHandler类结束。

因为Cleaner类是Java 9引入的,所以在早期版本的Java中无法使用。在早期版本中,可以使用finalize()方法来执行清理操作,但是这种方式已经被废弃,不建议使用。

总之,构造函数和析构函数是用于创建和销毁对象的特殊方法,可以在对象创建和销毁时执行必要的操作。在Java中,构造函数和析构函数被称为构造器和终结器,分别用于对象的初始化和销毁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值