Java 销毁对象

终结方法(finalizer)通常是不可预测的,也是很危险的,一般情况下是不必要的。使用终结方法会导致行为不稳定、降低性能,以及可移植性问题。

在Java中完成这样的工作主要是依靠try-finally机制来协助完成的,然而Java中还提供了另外一种被称为finalizer的机制,使用者仅仅需要重载Object对象提供的finalize方法,这样当JVM的在进行垃圾回收时,就可以自动调用该方法。但是由于对象何时被垃圾收集的不确定性,以及finalizer给GC带来的性能上的影响,因此并不推荐使用者依靠该方法来达到关键资源释放的目的。比如,有数千个图形句柄都在等待被终结和回收,可惜的是执行终结方法的线程优先级要低于普通的工作者线程,这样就会有大量的图形句柄资源停留在finalizer的队列中而不能被及时的释放,最终导致了系统运行效率的下降,甚至还会引发JVM报出OutOfMemoryError的错误。

Java的语言规范中并没有保证该方法会被及时的执行,甚至都没有保证一定会被执行。即便开发者在code中手工调用了
System.gc 和 System.runFinalization 这两个方法,这仅仅是提高了finalizer被执行的几率而已。还有一点需要注意的是,被重载的finalize()方法中如果抛出异常,其栈帧轨迹是不会被打印出来的。在Java中被推荐的资源释放方法为,提供显式的具有良好命名的接口方法,如
FileInputStream.close() 和 Graphic2D.dispose() 等。然后使用者在finally区块中调用该方法,见如下代码:

public void test() {
    FileInputStream fin = null;
    try {
        fin = new FileInputStream(filename);
        //do something.
    } finally {
        fin.close();
    }
}

在实际的开发中,利用finalizer又能给我们带来什么样的帮助呢?见下例:

public class FinalizeTest {
    //@Override
    protected void finalize() throws Throwable {
        try {
            //在调试过程中通过该方法,打印对象在被收集前的各种状态,
            //如判断是否仍有资源未被释放,或者是否有状态不一致的现象存在。
            //推荐将该finalize方法设计成仅在debug状态下可用,而在release
            //下该方法并不存在,以避免其对运行时效率的影响。
            System.out.println("The current status: " + _myStatus);
        } finally {
            //在finally中对超类finalize方法的调用是必须的,这样可以保证整个class继承
            //体系中的finalize链都被执行。
            super.finalize();
        }
    }
}
时间: 2024-10-17 11:37:30

Java 销毁对象的相关文章

《Effect Java》学习笔记1———创建和销毁对象

第二章 创建和销毁对象 1.考虑用静态工厂方法代替构造器 优势: 1.有名称 2.不必在每次调用它们的时候都创建一个新的对象:   3.可以返回原返回类型的任何子类型的对象: JDBC(Java Database Connectivity) 服务提供者框架(Service Provider Framework) 服务接口.提供者注册API.服务访问API.服务提供者接口(负责创建其服务实现的实例): 4.在创建参数类型实例的对象,它们使代码变得更加简洁 2.遇到多个构造器参数时,要考虑使用构造器

Effective Java 读书笔记(2创建和销毁对象)

第一章是引言,所以这里不做笔记,总结一下书中第一章的主要内容是向我们解释了这本书所做的事情:指导Java程序员如何编写出清晰.正确.可用.健壮.灵活和可维护的程序. 2.1考虑用静态工厂方法代替构造器 静态工厂方法与构造器相比有四大优势: (1)静态工厂方法有名称,具有适当名称的静态工厂方法易于使用.易于阅读: (2)不必每次在调用它们的时候都创建一个新的对象: (3)可以返回原返回类型的任何子类型的对象: (4)在创建参数化类型实例的时候,它们使代码变得更加简洁. 同时静态工厂方法也有两大缺点

Java进阶 创建和销毁对象

最近准备写点Javase的东西,希望可以帮助大家写出更好的代码. 1.给不可实例化的类提供私有构造器 比如:每个项目中都有很多工具类,提供了很多static类型的方法供大家使用,谁也不希望看到下面的代码: TextUtils textUtils = new TextUtils(); if(textUtils.isDigitsOnly("123")) { //doSometing }else { //doSomething } 自己写个工具类,总有人喜欢先初始化个实例在调用方法,然后还附

Effective Java:创建和销毁对象

前言: 读这本书第1条规则的时候就感觉到这是一本很好的书,可以把我们的Java功底提升一个档次,我还是比较推荐的.本博客是针对<Effective Java>这本书第2章所写的一篇读书笔记.博客中也有会一些个人对某个模块的理解和深入探究,希望与大家一起进步. 概述: 本章的主题是创建和销毁对象:何时以及如何创建对象,何时以及如何避免创建对象,如何确保它们能够适时地销毁,以及如何管理对象销毁之前必须进行的各种清理动作. 相关内容: 1.考虑用静态工厂方法代替构造器 思路解析: 如果有人问你,如何

Effective java 第二章创建和销毁对象 读书笔记

建和销毁对象 一般有两种方式,一种是获得本身的实例,最常用的方法就是提供一个共有的构造器.第二个方法是,类可以提供一个共有的静态工厂方法. 静态工厂方法与构造器不同的三大优势: 有名字: 调用时不用创建新的对象: 返回原来类型的任何子类型对象. 第四大优势: 在创建参数化类型实例的时候,它们使代码变得更加简洁. 服务提供者框架 三个组件: 服务接口 提供者主持API 服务访问API 可选: 服务提供者接口 静态工厂方法的缺点: 类如果不含共有的或者受保护的构造器,就不能被子类化: 它们与其他的静

Java的结构之美【2】——销毁对象

先来看一段代码: import java.util.Arrays; import java.util.EmptyStackException; /** * 2014年6月28日09:31:59 * @author 阳光小强 * */ public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITAL_CAPACITY = 15; public S

【Effective Java】创建和销毁对象

一.考虑用静态工厂方法代替构造器 构造器是创建一个对象实例的最基本最常用的方法.开发者在使用某个类的时候,通常会使用new一个构造器来实现,其实也有其他方式可以实现的,如利用发射机制.这里主要说的是通过静态类工厂的方式来创建class的实例,如: public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; } 静态工厂方法和构造器不同有以下主要优势: 1.有意义的名称. 可能有多个构造器,

effective java读书笔记1——创建和销毁对象

今天刚开始读effective java,中文版的读起来很拗口,但感觉收获很多. 另外,这本书的内容是针对Java 1.5和1.6的. 在这里整理一下第2章:创建和销毁对象 的内容. 第一条:考虑用静态工厂方法代替构造器 这一条针对的情景是要获得类的实例时.一般说来,想要获得类的实例,都是通过构造函数(书里叫做构造器). 最常见的构造函数是这样的,没有返回参数,名字和类名相同. public class A{ public A(int a){ //构造函数内容 ... } } 而所谓的静态工厂,

[Effective Java]第二章 创建和销毁对象

第一章      前言 略... 第二章      创建和销毁对象 1.            考虑用静态工厂方法代替构造器 创建对象方法:一是最常用的公有构造器,二是静态工厂方法.下面是一个Boolean的简单示例: public static Boolean valueOf(boolean b) { return (b ? Boolean.TRUE : Boolean.FALSE); } l  静态工厂方法与构造器不同的第一大优势在于,它们有名称. 作用不同的公有构造器只能通过参数来区别(因