终结方法finalize()通常是不可预测的,也是很危险的,一般情况下是不必要的。

  • Java语言规范并不保证finalize()会被及时执行,即不确定终结方法执行时间,只规定在对象被垃圾回收之前执行
  • 不应该依赖终结方法来改变重要的持久状态
  • 终结方法会造成严重的性能损耗

正确使用终结方法

  1. 防止用户使用了创建了对象后,并未使对象提供的显式终止方法(如果有)。终结方法可以充当安全网。

  2. 本地对等体(是一个本地对象,普通对象通过本地方法委托给一个本地对象。)不是一个普通对象,垃圾回收器不会回收它。一般情况下,终结方法需要能够完成所有必要的工作释放资源,如果需要即时释放资源,那么就需要给本地对等体指定一个显式的终止方法。

终结方法链不会自动执行,如果类有终结方法,并且子类覆盖了终结方法,则子类的终结方法必须手工调用超类的终结方法。你应该在try块中终结子类,并在相应的finally块中调用超类的终结方法。

终结方法守卫者

如果子类实现者覆盖了超类的终结方法,但是忘了调用超类的终结方法,那么超类的终结方法永远不会调用。为了防止此种情况出现,可以使用终结方法守卫者。即为每个被终结的对象创建一个附加的对象,该附加对象为一个匿名类,将外围类的终结操作如释放资源放入该匿名类的终结方法中。同时,外围类保存着对该匿名类的唯一引用,即复制给私有变量域。

 class A {

     @SuppressWarnings("unused")
//终结守卫者
private final Object finalizerGuardian = new Object() { @Override
//终结守卫者的终结方法将被执行
protected void finalize() {
System.out.println("A finalize by the finalizerGuardian");
}
}; @Override
//由于终结方法被子类覆盖,该终结方法并不会被执行
protected void finalize() {
System.out.println("A finalize by the finalize method");
} public static void main(String[] args) throws Exception {
B b = new B();
b = null;
System.gc();
Thread.sleep(500);
}
} class B extends A { @Override
public void finalize() {
System.out.println("B finalize by the finalize method");
} }

输出:

A finalize by the finalizerGuardian
B finalize by the finalize method

Java终结方法的使用(终结守卫者)的更多相关文章

  1. Java 终结方法 避免使用终结方法

    在Java中,当一个对象变得不可到达时,垃圾回收器会回收与该对象相关联的存储空间.用try-finally块来回收其他的非内存资源. 终结方法的缺点在于不能保证会被及时地执行.从一个对象变得不可到达开 ...

  2. EffectiveJava(7)避免使用终结方法

    避免使用终结方法 1.使用终结方法会导致行为不稳定,性能降低,以及可移植性的问题.(终结线程的优先级过低) 终结方法不能保证被及时的执行(从一个对象变得不可到达开始,到中介方法被执行,所花费的时间是任 ...

  3. effective java —— 终结方法守卫者

    目录: effective java —— 终结方法守卫者 effective java 第2章:创建和销毁对象.第7条 : 避免使用终结方法.最后的“终结方法守卫者 (finalizer guard ...

  4. [转]Java远程方法调用

    Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口.它使客户机上运行的程序可以调用远 ...

  5. Java:方法的参数是传值还是传引用

    Java中方法的参数总是采用传值的方式. 下列方法欲实现对象的交换,但实际上是不能实现的. public void swap(simpleClass a,simpleClass b){ simpleC ...

  6. Java之方法重载篇(我重载了,你要如何来调用我。。)

      一.课前引言 请看一下代码,你发现什么特殊之处了吗? public class MethodOverload { public static void main(String[] args) { ...

  7. Java parseInt()方法

    1.Java parseInt()方法 使用此方法得到的原始数据类型的一个特定的字符串. parseXxx()是一个静态方法,可以有一个参数或两个. java parseInt() 语法:   sta ...

  8. 几种任务调度的 Java 实现方法与比较

    综观目前的 Web 应用,多数应用都具备任务调度的功能.本文由浅入深介绍了几种任务调度的 Java 实现方法,包括 Timer,Scheduler, Quartz 以及 JCron Tab,并对其优缺 ...

  9. JNI系列——C文件中的方法调用Java中方法

    1.创建xxx.jni包并在该包下实现一些Java的方法,和要调用的本地方法 2.实现MainActivity中的按钮点击事件-即点击按钮调用本地的方法 3.在C文件中的方法中回调Java的方法 3. ...

随机推荐

  1. cfDNA基本知识

    定义 Circulating free DNA or Cell free DNA (cfDNA):循环游离DNA或者细胞游离DNA,释放到血浆中的降解的DNA片段. https://en.wikipe ...

  2. ASP.NET CORE入门之读取Json配置文件

    首先新建一.net core控制台项目,命名为jsonReader 然后选中引用,选择NuGet包管理器,点击浏览引入mircosoft.aspnetcore.all并安装 选中解决方案,填加,新建项 ...

  3. sql数据库设置自定义消息

    第一步 EXEC sp_addmessage   @msgnum =   50005 ,   @severity =   10 ,   @msgtext =   '更新失败'        ,  @l ...

  4. 在TextBox中敲击回车执行ASP.NET后台事件

    1.在TextBox中敲击回车执行ASP.NET后台事件   0.说明 页面中有一个用于搜索的TextBox,希望能在输入内容后直接回车开始搜索,而不是手动去点击它旁边的搜索按钮 但因为该TextBo ...

  5. ProgressBar、ProgessDialog用法解析

    一.ProgressBar 1. 常用类型 1.1 不确定式圆形进度条 style="@android:style/Widget.Holo.Light.ProgressBar" s ...

  6. 简单的cookie读写封装

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 【Luogu3768】简单的数学题(莫比乌斯反演,杜教筛)

    [Luogu3768]简单的数学题(莫比乌斯反演,杜教筛) 题面 洛谷 \[求\sum_{i=1}^n\sum_{j=1}^nijgcd(i,j)\] $ n<=10^9$ 题解 很明显的把\( ...

  8. 解决:安装oracle客户端,提示“oracle11g所选的主目录位于基目录外”

    安装oracle客户端,第三步下一步的时候,提示"oracle11g所选的主目录位于基目录外": 默认  Oracle基目录:D:\app\xxx 原      软件位置:F:\p ...

  9. PHP 反射类学习记录

    原文:http://www.upwqy.com/details/58.html 1 开发环境 windows TP5 参考文档 http://php.net/manual/zh/class.refle ...

  10. docker 使用案例:部署nginx

    首先安装docker.可以参考这篇教程: http://www.runoob.com/docker/windows-docker-install.html 本教程以windows10+ubuntu:1 ...