`
shootyou
  • 浏览: 84490 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

finalize()方法

阅读更多

以下转自:孙卫琴《Java面向对象编程

 

11.4.3 对象的finalize()方法简介

当垃圾回收器将要释放无用对象的内存时,先调用该对象的finalize()方法。如果在程序终止之前垃圾回收器始终没有执行垃圾回收操作,那么垃圾回收器将始终不会调用无用对象的finalize()方法。在Java的Object祖先类中提供了protected类型的finalize()方法,因此任何Java类都可以覆盖finalize()方法,在这个方法中进行释放对象所占的相关资源的操作。

Java虚拟机的垃圾回收操作对程序完全是透明的,因此程序无法预料某个无用对象的finalize()方法何时被调用。另外,除非垃圾回收器认为程序需要额外的内存,否则它不会试图释放无用对象占用的内存。换句话说,以下情况是完全可能的:一个程序只占用了少量内存,没有造成严重的内存需求,于是垃圾回收器没有释放那些无用对象占用的内存,因此这些对象的finalize()方法还没有被调用,程序就终止了。

程序即使显式调用System.gc()或Runtime.gc()方法,也不能保证垃圾回收操作一定执行,因此不能保证无用对象的finalize()方法一定被调用。

11.4.4 对象的finalize()方法的特点

对象的finalize()方法具有以下特点:

垃圾回收器是否会执行该方法及何时执行该方法,都是不确定的。

finalize()方法有可能使对象复活,使它恢复到可触及状态。

垃圾回收器在执行finalize()方法时,如果出现异常,垃圾回收器不会报告异常,程序继续正常运行。

下面结合一个具体的例子来解释finalize()方法的特点。例程11-13的Ghost类是一个带实例缓存的不可变类,它的finalize()方法能够把当前实例重新加入到实例缓存ghosts中。

例程11-13 Ghost.java

运行以上Ghost类的main()方法,一种可能的打印结果为:

Ghost@3179c3

execute finalize

Ghost@3179c3

以上程序创建了3个对象:1个Ghost对象、1个常量字符串“IAmBack”及1个HashMap对象。当程序执行完main()方法的第③行时,内存中引用变量与对象之间的关系如图11-9所示。

 

图11-9 Ghost对象与其他对象及引用变量的关系

当执行完第④行时,ghost变量被置为null,此时Ghost对象依然被ghosts属性间接引用,因此仍然处于可触及状态。当执行完第⑤行时,Ghost对象的引用从HashMap对象中删除,Ghost对象不再被程序引用,此时进入可复活状态,即变为无用对象。

第⑥行调用System.gc()方法,它能提高垃圾回收器尽快执行垃圾回收操作的可能性。假如垃圾回收器线程此刻获得了对CPU的使用权,它将调用Ghost对象的finalize()方法。该方法把Ghost对象的引用又加入到HashMap对象中,Ghost对象又回到可触及状态,垃圾回收器放弃回收它的内存。执行完第⑧行,ghost变量又引用这个Ghost对象。

假如对finalize()做一些修改,使它抛出一个异常:

protected void finalize()throws Throwable{

ghosts.put(name,this);

System.out.println("execute finalize");

throw new Exception("Just Test");

}

程序的打印结果不变。由此可见,当垃圾回收器执行finalize()方法时,如果出现异常,垃圾回收器不会报告异常,也不会导致程序异常中断。

假如在程序运行中,垃圾回收器始终没有执行垃圾回收操作,那么Ghost对象的finalize()方法就不会被调用。读者不妨把第⑥行的System.gc()和第⑦行的Thread.sleep(3000)方法注释掉,这样更加可能导致finalize()方法不会被调用,此时程序的一种可能的打印结果为:

Ghost@3179c3

Ghost@310d42

从以上打印结果可以看出,由于Ghost对象的finalize()方法没有被执行,因此这个Ghost对象在程序运行期间始终没有复活。当程序第二次调用Ghost.getInstance("IAmBack")方法时,该方法创建了一个新的Ghost对象。

值得注意的是,以上例子仅仅用于演示finalize()方法的特性,在实际应用中,不提倡用finalize()方法来复活对象。可以把处于可触及状态的对象比做活在阳间的人,把不处于这个状态的对象(无用对象)比做到了阴间的人。程序所能看见和使用的是阳间的人,假如阎王经常悄悄地让几个阴间的人复活,使他们在程序毫不知情的情况下溜回阳间,这只会扰乱程序的正常执行流程。

11.4.5 比较finalize()方法和finally代码块

在Object类中提供了finalize()方法,它的初衷是用于在对象被垃圾回收器回收之前,释放所占用的相关资源,这和try…catch…finally语句的finally代码块的用途比较相似。但由于垃圾回收器是否会执行finalize()方法及何时执行该方法,都是不确定的,因此在程序中不能用finalize()方法来完成同时具有以下两个特点的释放资源的操作。

必须执行。

必须在某个确定的时刻执行。

具有以上特点的操作更适合于放在finally代码块中。此外,可以在类中专门提供一个用于释放资源的公共方法,最典型的就是java.io.InputStream和java.io.OutputStream类的close()方法,它们用于关闭输入流或输出流。当程序中使用了一个输入流时,在结束使用前应该确保关闭输入流。

InputStream in;

try{

InputStream in=new FileInputStream("a.txt");

}catch(IOException e){

}finally{

try{in.close();}catch(IOException e){…}

}

在多数情况下,应该避免使用finalize()方法,因为它会导致程序运行结果的不确定性。在某些情况下,finalize()方法可用来充当第二层安全保护网,当用户忘记显式释放相关资源时,finalize()方法可以完成这一收尾工作。尽管finalize()方法不一定会被执行,但是有可能会释放资源,这总比永远不会释放资源更安全。

可以用自动洗衣机的关机功能来解释finalize()方法的用途。自动洗衣机向用户提供了专门的关机按钮,这相当于AutoWasher类的close()方法,假如用户忘记关机,相当于忘记调用AutoWasher对象的close()方法,那么自动洗衣机会在洗衣机停止工作后的1个小时内自动关机,这相当于调用finalize()方法。当然,这个例子不是太贴切,因为如果用户忘记关机,洗衣机的自动关机操作总会被执行。

<!-- page -->

分享到:
评论

相关推荐

    Java中finalize方法使用.doc

    Java 中 finalize 方法使用 finalize 方法是 Java 编程语言中一个非常重要的方法,它与 Java 编程中的垃圾回收器有着紧密的关系。当一个对象变成一个垃圾对象的时候,如果此对象的内存被回收,那么就可以调用系统中...

    Java禁止使用finalize方法共2页.pdf.zip

    在Java编程语言中,`finalize()`方法是一个特殊的方法,它属于`Object`类,主要用于对象销毁前执行一些必要的清理工作。然而,随着Java版本的更新和垃圾收集机制的改进,`finalize()`方法逐渐失去了其原本的重要性,...

    Java禁止使用finalize方法

    Java禁止使用finalize方法 Java中的finalize方法是一个特殊的方法,位于Java.lang.Object类中,它的主要作用是允许开发者在对象被垃圾回收前执行一些清理工作。但是,finalize方法存在许多问题,导致它不被推荐使用...

    Java中finalize方法.pdf

    Java中的`finalize()`方法是Java语言提供的一种机制,用于在对象被垃圾回收之前进行资源清理。这个方法在Java的`Object`类中被定义为`protected`类型,因此所有Java类都能够覆盖它来实现特定的清理操作。在垃圾回收...

    Java中finalize()的用法

    Java 中的 finalize() 方法是垃圾回收器在回收对象时调用的第一个方法。finalize() 方法相当于析构函数,它是垃圾回收器回收一个对象时第一个要调用的方法。finalize() 方法的主要作用是释放对象占用的系统资源,...

    Java垃圾回收机制的finalize方法实例分析

    Java垃圾回收机制的finalize方法实例分析 Java垃圾回收机制的finalize方法是垃圾回收机制中一个非常重要的概念,它可以帮助开发者更好地理解和掌握垃圾回收机制的工作机理。本文将通过实例形式分析finalize方法的...

    简单理解Java的垃圾回收机制与finalize方法的作用

    Java中的`finalize()`方法是对象生命周期的一部分,它与C++中的析构函数类似,但在功能和调用时机上有所不同。`finalize()`方法是在对象被GC标记为可回收并准备释放之前调用的,提供了在对象被彻底删除前执行某些...

    Java中针对finalize的实现和相应的执行过程

     这个引用对象专门为带finalize方法的类服务,可以理解为每一个有相应的方法的对象,其都会封装为一种finalRefernece对象.  因为finalize方法是object定义的,其默认实现为空.那么如果重写了此方法,那么方法体...

    c#中的非托管资源释放 (Finalize和Dispose)

    #### Finalize方法 1. **Finalize**方法是一种用于释放非托管资源的方法之一。它通常是在对象即将被垃圾回收器销毁之前由系统调用的。该方法可以用来释放任何未被CLR管理的资源。 2. 要实现`Finalize`方法,需要...

    Java中覆盖finalize()方法实例代码

    Java中的finalize()方法覆盖实例代码详解 finalize()方法是Java中的一个特殊方法,它可以在对象被垃圾回收器回收之前执行一次。这个方法可以用来释放对象持有的资源,但是它的使用需要非常小心,因为它带有很多不...

    finalfinally和finalize的区别共2页.p

    // 调用父类的finalize方法 System.out.println("对象正在被垃圾回收..."); // 在这里进行资源释放操作 } ``` 总结一下,`final` 关键字用于声明常量、防止继承和覆盖;`finally` 用于保证异常处理中的关键代码...

    C++程序员容易犯的十个C#错误

    为此,需要调用静态方法GC.SuppressFinalize,并将相应对象的指针传递给它作为参数,垃圾收集程序就不会在回收内存前对该对象调用Finalize方法。 错误6:没有正确地理解.NET Framework的垃圾收集机制 C#程序员需要...

    第3讲 谈谈final、finally、 finalize有什么不同1

    **finalize方法** `Object`类中的`finalize()`方法是为了在对象被垃圾收集之前执行清理操作而设计的。然而,这个机制并不高效且不可靠,因为垃圾收集的时机不确定,而且可能导致性能下降。从Java 9开始,`finalize`...

    JAVA中销毁一个对象的方法.doc

    JAVA 中销毁一个对象的方法可以分为三种:垃圾回收器、finalize 方法和 System.gc 方法。 方法一:垃圾回收器 垃圾回收器是 Java 平台中用的最频繁的一种对象销毁方法。垃圾回收器会全程侦测 Java 应用程序的运行...

    Java中final,finally,finalize三个关键字的区别_动力节点Java学院整理

    final 关键字用于限制变量、方法和类的修改和继承,finally 块用于异常处理中的清理操作,finalize 方法用于垃圾回收器执行内存对象清理时的清理工作。了解这三个关键字的区别可以帮助我们更好地编写 Java 代码,...

    java 常用类

    在这篇文章中,我们将讨论一些 Java 中最常用的类,包括 Object 类、String 类、equals 和 == 的区别、finalize 方法的作用、hashCode() 方法、toString() 方法等。 hashCode() 方法 hashCode() 方法是 Object 类...

    3谈谈final、finally、finaliz1

    finalize方法是Java中Object类的一个方法,其初衷是提供一个机会在对象被垃圾收集器回收之前执行特定的清理操作。然而,这个机制在实际使用中存在诸多问题,比如执行时机不确定、性能开销、可能导致对象复活等问题。...

    java虚拟机垃圾回收详解

    在对象被销毁之前,垃圾回收器会执行对象的finalize方法,并清除finalizable标志。因此,一个简单对象的生命周期通常经历Unfinalized、Finalizable、Finalized和Reclaimed四个阶段。 在Java中,`System.gc()`方法...

    JAVA基础面试题,包含答案

    在垃圾收集器将对象从内存中清除出去之前,finalize 方法名允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。 二、 int 和 Integer 的区别 int 是基本数据类型,Integer 是其...

    C#多线程开发多个实例

    //为false时肯定是GC调用了对象的Finalize方法,所以没有必要再告诉GC你不要调用我的Finalize方法啦 if (disposing) { GC.SuppressFinalize(this); } } } static void Main(string[] args) { //tmpObj1...

Global site tag (gtag.js) - Google Analytics