Think in java 笔记之 finalize() 函数

Posted long-ge-ge

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Think in java 笔记之 finalize() 函数相关的知识,希望对你有一定的参考价值。

1. java垃圾收集机制概述

  Javanew关键字生成的对象放在堆空间中,引用句柄则放在栈空间中。一个对象可以有多个引用。由于垃圾收集器的存在,对象是没有作用域的,引用句柄才有作用域。所以,当该对象的最后一个引用的作用域结束,或者该对象的最后一个引用指向了另一个对象或null,也就是说当该对象已经没有被任何引用句柄所引用的时候,该对象就可以被java垃圾收集器所回收了。回收发生的时间是不确定的,不过可以调用gc()方法通知jvm回收垃圾。

 

2. finalize()方法

 

  它是object类的一个protected方法,在垃圾收集器回收该对象之前调用自己。

3. finalize()的调用

 

程序退出时;

 

显示调用时;

 

 我们来讨论最重要的第三种:

 

java垃圾收集器在回收这个对象之前,将会调用这个对象的finalize()方法,一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存。所以如果使用finalize(),就可以在垃圾收集期间进行一些重要的清除或清扫工作。(该处引用了Think in java中的一句话)。程序验证如下

package chapter.one;

public class Garbage 
{
    @SuppressWarnings("deprecation")
    public static void main(String[] args) {
        if(args.length == 0) 
        {
            System.err.println("Usage: \n" +"java Garbage before\n or:\n" +
            "java Garbage after");
            return;
        }
        
        //循环
        while(!Chair.f) 
        {
            
            new Chair();
            new String("To take up space");
        }
        
        System.out.println("After all Chairs have been created:\n" +
                "total created = " + Chair.created +
                ", total finalized = " + Chair.finalized);
        
        if(args[0].equals("before")) 
        {
            System.out.println("gc():");
            System.gc();
            System.out.println("runFinalization():");
            System.runFinalization();
        }
        
        System.out.println("bye!");
        if(args[0].equals("after"))
        System.runFinalizersOnExit(true);
    }
}

class Chair
{
    static boolean gcrun = false;
    static boolean f = false;
    static int created = 0;        //static用来统计创建的对象的个数
    static int finalized = 0;
    int i;
    
    
    Chair() 
    {
        i = ++created;
        if(created == 47)
        System.out.println("Created 47");
    }
    
    
    //在垃圾回收之前调用
    @Override
    protected void finalize()
    {
//        gcrun的标记来指出垃圾收集器是否已经开始运行。    
        if(!gcrun)
        {
            gcrun = true;
            System.out.println("Beginning to finalize after " +created + 
                    " Chairs have been created");
        }
        //当f等于true的时候main函数应该停止对象的生成
        if(i == 47) 
        {
            System.out.println("Finalizing Chair #47, " +
            "Setting flag to stop Chair creation");
            f = true;
        }
        
        finalized++;
        if(finalized >= created)
            System.out.println("All " + finalized + " finalized");
    }
}

运行效果:

Created 47
Beginning to finalize after 231850 Chairs have been created
Finalizing Chair #47, Setting flag to stop Chair creation
After all Chairs have been created:
total created = 2476964, total finalized = 1403452
gc():
runFinalization():
bye!

 

 

4. 为何要定义finalize()方法

  有时当撤消一个对象时,需要完成一些操作。例如,如果一个对象正在处理的是非Java 资源,如文件句柄或window 字符字体(该处示例以后补充),这时你要确认在一个对象被撤消以前要保证这些资源被释放。为处理这样的状况,Java 提供了被称为收尾(finalization )的机制。

(因为无法保证是什么时候,所以不提倡使用这个方法)使用该机制你可以定义一些特殊的操作,这些操作在一个对象将要被垃圾回收程序释放时执行。 
要给一个类增加收尾(finalizer ),你只要定义finalize ( ) 方法即可。Java 回收该类的一个对象时,就会调用这个方法。

总的来说,就是你想在干对象被回收之前做点儿什么事儿,那么将该事件写进finalize()函数中,而且这件事儿还得不是特别急。  

5. finalize()方法并不是万能的

 

  比如当对象占用了很多的系统资源的时候。这个时候就不能放其不管而等着垃圾回收器来回收了,因为垃圾回收的发生------得看jvm的心情,因此,你的函数就应该提供其它的方法在该对象的引用清零之前,回收该对象所占用的资源。

 

以上是关于Think in java 笔记之 finalize() 函数的主要内容,如果未能解决你的问题,请参考以下文章

think in java 笔记

读书笔记《think in Java》①

读书笔记《think in Java》①

Think in java读书笔记序列化

Think In Java读书笔记:内部类覆盖及其初始化

Think In OO