Java:终结器防卫者,顺便看一下 C# 如何做的。
背景
多数情况我们不需要重写 finalize 方法,只有当我们需要持有未托管资源的时候才需要,而此时重写 finalize 方法,只是作为一个“安全网”,不能作为常规的资源释放模式,必须提供显式的释放方法,如:close。
如果某个类型重写了 finalize 方法,但是这个类型是可以继承的,这就要求所有的子类如果也重写了 finalize,就必须要调用父类的 finalize 方法,我们有三种策略:
- 按照约定。
- 终结器防卫者。
- 模板方法模式。
本文就介绍第 2 种模式,此模式是昨天看《Effective Java 第二版》时学习的,本文后面会介绍 C# 是如何做的。
Java版:终结器防卫者
测试代码
注意看注释,我就不多说了。
public class Program {
public static void main(String[] args) throws InterruptedException {
{
new CustomResourceOwner().doSomeThing();
}
System.gc();
System.out.println("程序结束!");
}
}
class ResourceOwnerBase {
// 可以将父类中 finalize 的代码放到守卫者里,一定会被调用的。
@SuppressWarnings("unused")
private final Object finalizeGuarder = new Object() {
@Override
public void finalize() {
System.out.println("在资源守卫者中销毁父类!");
}
};
// 子类可能故意不调用父类!
@Override
public void finalize() {
System.out.println("销毁父类!");
}
}
final class CustomResourceOwner extends ResourceOwnerBase {
@Override
public void finalize() {
System.out.println("销毁子类!");
// 故意不调用父类!
// super.finalize();
}
public void doSomeThing() {
System.out.println("随便做点工作!");
}
}
输出结果
随便做点工作!
程序结束!
在资源守卫者中销毁父类!
销毁子类!
说明
因为终结器防卫者只被资源拥有者持有,当资源拥有者变为垃圾的时候,终结器防卫者也会变为垃圾。
C#版:“终结器防卫者”
测试代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO; namespace DisposeStudy
{
class Program
{
static void Main()
{
{
var res = new CustomResourceOwner(IntPtr.Zero);
res.DoSomeThing();
}
}
} class ResourceOwnerBase : IDisposable
{
private bool _disposed;
private readonly FileStream _fileStream;
private IntPtr _handle; protected ResourceOwnerBase(IntPtr handle)
{
_handle = handle;
_fileStream = File.OpenRead(@"E:\Coding\HappyStudy\DisposeStudy\DisposeStudy\Program.cs");
} protected bool Disposed
{
get { return _disposed; }
} public void Dispose()
{
Dispose(true); GC.SuppressFinalize(this);
} protected virtual void Dispose(bool disposing)
{
if (Disposed)
{
if (disposing)
{
_fileStream.Dispose();
} CloseHandle(_handle);
_handle = IntPtr.Zero; _disposed = true;
}
} ~ResourceOwnerBase()
{
Console.WriteLine("父类析构方法!");
Dispose(false);
} [System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
} sealed class CustomResourceOwner : ResourceOwnerBase
{
public CustomResourceOwner(IntPtr handle)
: base(handle)
{
} public void DoSomeThing()
{
if (Disposed)
{
throw new ObjectDisposedException("资源已经消耗了,不能执行此操作!");
} Console.WriteLine("随便做点工作!");
} ~CustomResourceOwner()
{
Console.WriteLine("子类析构方法!");
}
}
}
输出结果

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

看完大家就明白了,C#在编译器层面保证了子类的终结器一定会调用父类的终结器。
备注
同时学习 C# 和 Java 是一件挺快乐的事情。
Java:终结器防卫者,顺便看一下 C# 如何做的。的更多相关文章
- Java:终结器
目录 背景Java版:终结器防卫者C#版:“终结器防卫者”备注 背景返回目录 多数情况我们不需要重写 finalize 方法,只有当我们需要持有未托管资源的时候才需要,而此时重写 finalize 方 ...
- Java类加载器( 死磕 4)
[正文]Java类加载器( CLassLoader ) 死磕 之4: 神秘的双亲委托机制 本小节目录 4.1. 每个类加载器都有一个parent父加载器 4.2. 类加载器之间的层次关系 4.3. ...
- JVM强引用、软引用、弱引用、虚引用、终结器引用垃圾回收行为总结
JVM引用 我们希望能描述这样一类对象: 当内存空间还足够时,则能保留在内存中:如果内存空间在进行垃圾收集后还是很紧张,则可以抛弃这些对象. -[既偏门又非常高频的面试题]强引用.软引用.弱引用.虚引 ...
- 深入理解Java类加载器(二):线程上下文类加载器
摘要: 博文<深入理解Java类加载器(一):Java类加载原理解析>提到的类加载器的双亲委派模型并不是一个强制性的约束模型,而是Java设计者推荐给开发者的类加载器的实现方式.在Java ...
- java类加载器深入研究
看了下面几篇关于类的加载器的文章,豁然开朗.猛击下面的地址开始看吧. Java类加载原理解析 深入探讨 Java 类加载器 分析BootstrapClassLoader/ExtClassLo ...
- 深入探讨 Java 类加载器
转自:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器(class loader)是 Java™中的一个很重要的概念.类 ...
- 高性能Java解析器实现过程详解
如果你没有指定数据或语言标准的或开源的Java解析器, 可能经常要用Java实现你自己的数据或语言解析器.或者,可能有很多解析器可选,但是要么太慢,要么太耗内存,或者没有你需要的特定功能.或者开源解析 ...
- 深入探讨 Java 类加载器[转]
原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html 类加载器(class loader)是 Java™ ...
- 转载:深入探讨 Java 类加载器
转载地址 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 深入探讨 Java 类加载器 类加载器(class loader) ...
随机推荐
- 一键去除网页BOM属性【解决乱码,头部空白,问题】
几个常出现的问题: 1.网站打开空白 2.页面头部出现多余的空白 3.网站出现乱码,如“锘�” 解决方法可以是: 1.选用专业的编辑器,例如notepad++,sublime,editplus这样不会 ...
- C++构造函数详解(复制构造函数)
构造函数是干什么的 该类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作,故:构造函数的作用:初始化对象的数据成员. 构造函数的种类 class Compl ...
- 【转载】OpenMAXIL介绍与其体系
1 OpenMAX IL介绍与其体系 这一部分的文档描述 OpenMAX IL的特性与体系. 1.1 OpenMAX IL 简述 OpenMAX IL 软件接口层定义了一套API,用于访问系统中的组件 ...
- JS获取select的value和text值的简单实例
本篇文章主要是对JS获取select的value和text值的简单实例进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助 代码如下: <select id = "cityList ...
- java 可变参数讲解
java5中新增了可变参数,这个可变参数和C语言中的用法是差不多,但实现起来却不一样. 下面我们一起来看看吧. 其实可变参数就是一个数组 class A{ public void func(int.. ...
- 《java虚拟机》----虚拟机字节码执行引擎
No1: 物理机的执行引擎是直接建立在处理器.硬件.指令集合操作系统层面上的,而虚拟机的执行引擎则是由自己实现的,因此可以自行制定指令集与执行引擎的结构体系,并且能够执行那些不被硬件直接支持的指令集格 ...
- 洛谷——P1894 [USACO4.2]完美的牛栏The Perfect Stall
P1894 [USACO4.2]完美的牛栏The Perfect Stall 题目描述 农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术.不幸的是,由于工程问题,每个牛栏都不一样.第一个星 ...
- FastReport.Net使用:[19]复选框的使用
FastReport中,用好复选框会使报表更美观. 复选框的用法举例: 1.点菜系统中,打印用户点菜时,将已点的菜进行打“√”标记等. 2.选课系统中,将已选科目进行打“√”等. 认识复选框 复选框只 ...
- 【BZOJ 2121】 (字符串DP,区间DP)
2121: 字符串游戏 Description BX正在进行一个字符串游戏,他手上有一个字符串L,以及其他一些字符串的集合S,然后他可以进行以下操作:对于一个在集合S中的字符串p,如果p在L中出现,B ...
- 我的OI生涯番外篇
番外篇 转眼间我学oi已经一年了,可回头想想这一年来的收获也没有什么,大部分时间都荒废掉了. 下半年开学后,学物竞的王洋转来了我们电竞,虽然他之前是我的同班同学但也没怎么交流过. 这下我们又成为了oi ...