Java:终结器
目录
背景返回目录
多数情况我们不需要重写 finalize 方法,只有当我们需要持有未托管资源的时候才需要,而此时重写 finalize 方法,只是作为一个“安全网”,不能作为常规的资源释放模式,必须提供显式的释放方法,如:close。
如果某个类型重写了 finalize 方法,但是这个类型是可以继承的,这就要求所有的子类如果也重写了 finalize,就必须要调用父类的 finalize 方法,我们有三种策略:
- 按照约定。
- 终结器防卫者。
- 模板方法模式。
本文就介绍第 2 种模式,此模式是昨天看《Effective Java 第二版》时学习的,本文后面会介绍 C# 是如何做的。
Java版:终结器防卫者返回目录
测试代码
注意看注释,我就不多说了。

1 public class Program {
2
3 public static void main(String[] args) throws InterruptedException {
4 {
5 new CustomResourceOwner().doSomeThing();
6 }
7
8 System.gc();
9
10 System.out.println("程序结束!");
11 }
12 }
13
14 class ResourceOwnerBase {
15 // 可以将父类中 finalize 的代码放到守卫者里,一定会被调用的。
16 @SuppressWarnings("unused")
17 private final Object finalizeGuarder = new Object() {
18 @Override
19 public void finalize() {
20 System.out.println("在资源守卫者中销毁父类!");
21 }
22 };
23
24 // 子类可能故意不调用父类!
25 @Override
26 public void finalize() {
27 System.out.println("销毁父类!");
28 }
29 }
30
31 final class CustomResourceOwner extends ResourceOwnerBase {
32 @Override
33 public void finalize() {
34 System.out.println("销毁子类!");
35
36 // 故意不调用父类!
37 // super.finalize();
38 }
39
40 public void doSomeThing() {
41 System.out.println("随便做点工作!");
42 }
43 }

输出结果
1 随便做点工作!
2 程序结束!
3 在资源守卫者中销毁父类!
4 销毁子类!
说明
因为终结器防卫者只被资源拥有者持有,当资源拥有者变为垃圾的时候,终结器防卫者也会变为垃圾。
C#版:“终结器防卫者”返回目录
测试代码

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using System.IO;
7
8 namespace DisposeStudy
9 {
10 class Program
11 {
12 static void Main()
13 {
14 {
15 var res = new CustomResourceOwner(IntPtr.Zero);
16 res.DoSomeThing();
17 }
18 }
19 }
20
21 class ResourceOwnerBase : IDisposable
22 {
23 private bool _disposed;
24 private readonly FileStream _fileStream;
25 private IntPtr _handle;
26
27 protected ResourceOwnerBase(IntPtr handle)
28 {
29 _handle = handle;
30 _fileStream = File.OpenRead(@"E:\Coding\HappyStudy\DisposeStudy\DisposeStudy\Program.cs");
31 }
32
33 protected bool Disposed
34 {
35 get { return _disposed; }
36 }
37
38 public void Dispose()
39 {
40 Dispose(true);
41
42 GC.SuppressFinalize(this);
43 }
44
45 protected virtual void Dispose(bool disposing)
46 {
47 if (Disposed)
48 {
49 if (disposing)
50 {
51 _fileStream.Dispose();
52 }
53
54 CloseHandle(_handle);
55 _handle = IntPtr.Zero;
56
57 _disposed = true;
58 }
59 }
60
61 ~ResourceOwnerBase()
62 {
63 Console.WriteLine("父类析构方法!");
64 Dispose(false);
65 }
66
67 [System.Runtime.InteropServices.DllImport("Kernel32")]
68 private extern static Boolean CloseHandle(IntPtr handle);
69 }
70
71 sealed class CustomResourceOwner : ResourceOwnerBase
72 {
73 public CustomResourceOwner(IntPtr handle)
74 : base(handle)
75 {
76 }
77
78 public void DoSomeThing()
79 {
80 if (Disposed)
81 {
82 throw new ObjectDisposedException("资源已经消耗了,不能执行此操作!");
83 }
84
85 Console.WriteLine("随便做点工作!");
86 }
87
88 ~CustomResourceOwner()
89 {
90 Console.WriteLine("子类析构方法!");
91 }
92 }
93 }

输出结果

说明
让我们看看编译器帮我们做了什么工作:

看完大家就明白了,C#在编译器层面保证了子类的终结器一定会调用父类的终结器。
备注返回目录
同时学习 C# 和 Java 是一件挺快乐的事情。
Java:终结器防卫者
Java:终结器的更多相关文章
- Java:终结器防卫者,顺便看一下 C# 如何做的。
背景 多数情况我们不需要重写 finalize 方法,只有当我们需要持有未托管资源的时候才需要,而此时重写 finalize 方法,只是作为一个“安全网”,不能作为常规的资源释放模式,必须提供显式的释 ...
- JVM强引用、软引用、弱引用、虚引用、终结器引用垃圾回收行为总结
JVM引用 我们希望能描述这样一类对象: 当内存空间还足够时,则能保留在内存中:如果内存空间在进行垃圾收集后还是很紧张,则可以抛弃这些对象. -[既偏门又非常高频的面试题]强引用.软引用.弱引用.虚引 ...
- java笔记--理解java类加载器以及ClassLoader类
类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制 ...
- java安全管理器SecurityManager入门
table { margin-left: 30px; width: 95%; border: 1px; border-collapse: collapse } img { border: 1px so ...
- java类加载器深入研究
看了下面几篇关于类的加载器的文章,豁然开朗.猛击下面的地址开始看吧. Java类加载原理解析 深入探讨 Java 类加载器 分析BootstrapClassLoader/ExtClassLo ...
- effective java —— 终结方法守卫者
目录: effective java —— 终结方法守卫者 effective java 第2章:创建和销毁对象.第7条 : 避免使用终结方法.最后的“终结方法守卫者 (finalizer guard ...
- 深入探讨 Java 类加载器
转自:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器(class loader)是 Java™中的一个很重要的概念.类 ...
- 高性能Java解析器实现过程详解
如果你没有指定数据或语言标准的或开源的Java解析器, 可能经常要用Java实现你自己的数据或语言解析器.或者,可能有很多解析器可选,但是要么太慢,要么太耗内存,或者没有你需要的特定功能.或者开源解析 ...
- JAVA 类加载器 第14节
JAVA 类加载器 第14节 今天我们将类加载机制5个阶段中的第一个阶段,加载,又叫做装载.为了阅读好区分,以下都叫做装载. 装载的第一步就是要获得二进制的字节流,它可以从读.class文件获得,也可 ...
随机推荐
- 解决Crystal Report XI R2不能在64操作系统正常工作的问题-web程序
原文:[原创]解决Crystal Report XI R2不能在64操作系统正常工作的问题-web程序 我更换了新的电脑,操作系统也从原来32位的windows 2003 R2升级到windows 2 ...
- FPGA笔记-阅读.dat文件
阅读.dat图像文件 .dat文件是matlab生成的图像文件 initial begin // Initialize Inputs CLK = 0; RST = 1; IMAGE_DATA = 0; ...
- TLD跟踪算法优化(一)并行化
才学疏浅,仅仅言片语,仅仅求志同道的朋友一起交流研究. 并行化不算是算法的改进,仅仅是追求执行的实时性. 简要列举一个样例: TLD算法的C++版本号源代码里: LKTracker::trackf2f ...
- iOS开发---转换坐标系
- (void)viewDidLoad { [super viewDidLoad]; // 蓝色 UIView *blue = [[UIView alloc] init]; blue.backgrou ...
- .NET:从 Mono、.NET Core 说起
魅力 .NET:从 Mono..NET Core 说起 前段时间,被问了这样一个问题:.NET 应用程序是怎么运行的? 当时大概愣了好久,好像也没说出个所以然,得到的回复是:这是 .NET 程序员最基 ...
- java设计模式之五原型模式(Prototype)
原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制.克隆,产生一个和原对象类似的新对象.本小结会通过对象的复制,进行讲解.在Java中 ...
- JAVA基本的编程50称号(7-9称号)详细解释
一个.叙述性说明 1.输入一行字符.在这些信件统计.空格.出现频率的数字和其他字符的总数和每一个字符. 程序分析:使用String类的matchs()分别统计符合正則表達式的每类字符的 ...
- CSS知识总结之浏览器(持续更新)
web页面浏览器渲染过程 1.解析html文件,并构建DOM树: 在DOM树中,每一个html标签都有一个对应的节点,并且每一个文本也有一个对应 的节点(js的textNode),DOM树的根节点就是 ...
- vim打开出现的文档^M什么
网上公开的一些代码,发现里面多^M符号.这是什么? 我搜索^M没有效果,这应该是一个特殊的控制字符.找换行的结果是不.在每一行的末尾是回车,代替它周围包裹,对于由线定义不同的编码系统是不一样的. li ...
- PHP 15:异常
原文:PHP 15:异常 看完了out_put_fns.php文件,让我们再看看db_fns.php文件.其代码非常简单,如下: ?> 其作用是连接数据库,并返回一个数据库连接.在这里我们 ...