目录

背景Java版:终结器防卫者C#版:“终结器防卫者”备注

背景返回目录

多数情况我们不需要重写 finalize 方法,只有当我们需要持有未托管资源的时候才需要,而此时重写 finalize 方法,只是作为一个“安全网”,不能作为常规的资源释放模式,必须提供显式的释放方法,如:close。

如果某个类型重写了 finalize 方法,但是这个类型是可以继承的,这就要求所有的子类如果也重写了 finalize,就必须要调用父类的 finalize 方法,我们有三种策略:

  1. 按照约定。
  2. 终结器防卫者。
  3. 模板方法模式。

本文就介绍第 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:终结器的更多相关文章

  1. Java:终结器防卫者,顺便看一下 C# 如何做的。

    背景 多数情况我们不需要重写 finalize 方法,只有当我们需要持有未托管资源的时候才需要,而此时重写 finalize 方法,只是作为一个“安全网”,不能作为常规的资源释放模式,必须提供显式的释 ...

  2. JVM强引用、软引用、弱引用、虚引用、终结器引用垃圾回收行为总结

    JVM引用 我们希望能描述这样一类对象: 当内存空间还足够时,则能保留在内存中:如果内存空间在进行垃圾收集后还是很紧张,则可以抛弃这些对象. -[既偏门又非常高频的面试题]强引用.软引用.弱引用.虚引 ...

  3. java笔记--理解java类加载器以及ClassLoader类

    类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制 ...

  4. java安全管理器SecurityManager入门

    table { margin-left: 30px; width: 95%; border: 1px; border-collapse: collapse } img { border: 1px so ...

  5. java类加载器深入研究

    看了下面几篇关于类的加载器的文章,豁然开朗.猛击下面的地址开始看吧. Java类加载原理解析      深入探讨 Java 类加载器 分析BootstrapClassLoader/ExtClassLo ...

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

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

  7. 深入探讨 Java 类加载器

    转自:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器(class loader)是 Java™中的一个很重要的概念.类 ...

  8. 高性能Java解析器实现过程详解

    如果你没有指定数据或语言标准的或开源的Java解析器, 可能经常要用Java实现你自己的数据或语言解析器.或者,可能有很多解析器可选,但是要么太慢,要么太耗内存,或者没有你需要的特定功能.或者开源解析 ...

  9. JAVA 类加载器 第14节

    JAVA 类加载器 第14节 今天我们将类加载机制5个阶段中的第一个阶段,加载,又叫做装载.为了阅读好区分,以下都叫做装载. 装载的第一步就是要获得二进制的字节流,它可以从读.class文件获得,也可 ...

随机推荐

  1. crm使用soap删除实体

    //C# 代码: //DeleteEntityRequest request = new DeleteEntityRequest(); //request.LogicalName = "ne ...

  2. c++的string容器

    c++相比c的一个好处就是实现了很多的容器和泛型算法,使得程序员的工作得到了很大的化简.其中一个很有用的泛型容器就是string.string是一个类,是一个在STL里边实现好了的类,由于他的很多功能 ...

  3. 物理引擎Havok教程(一)搭建开发环境

    物理引擎Havok教程(一)搭建开发环境 网上关于Havok的教程实在不多,并且Havok学习起来还是有一定难度的,所以这里写了一个系列教程,希望可以帮到读者.这是第一期. 一.Havok物理引擎简单 ...

  4. 文档流 css中间float clear和布局

    文档流 先说说什么是公文流转  什么流 它是一系列连续的东西 <div style="background-color:pink;width:40px;height:80px;&quo ...

  5. Java NIO的多路复用及reactor

    (from:http://developer.51cto.com/art/201112/306489.htm) 以下描述,为了说明问题,就提提历史(类似的东西,网上一搜一大把,但是希望你能在这里止步, ...

  6. update与fixedupdate差别

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网--Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=307 今天有人问我问什么我在处 ...

  7. 关于webbrowser控件自动登陆的问题

    原文:关于webbrowser控件自动登陆的问题 楼主dtb(陈少)2004-03-04 22:16:55 在 VB / 网络编程 提问 请问怎么用webbrowser自动登陆www.jp168.co ...

  8. memcpy源代码

    7月22号去面试开发的职位,面试官先问我在以前项目中写了什么程序.我就巴拉巴拉的说了一堆写过的code,主要还是测试工具和自动化测试代码.之后让我写memcpy的函数,面试官还挺好的,帮我把函数原型都 ...

  9. App.config

      App.config的学习笔记 昨天基本弄清config的使用之后,再看WP的API,晕了.结果WP不支持system.configuration命名空间,这意味着想在WP上用App.config ...

  10. python进程池剖析(二)

    之前文章中介绍了python中multiprocessing模块中自带的进程池Pool,并对进程池中的数据结构和各个线程之间的合作关系进行了简单分析,这节来看下客户端如何对向进程池分配任务,并获取结果 ...