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) ...
随机推荐
- 结构体对齐及#pragma详细解释
在linux下c语言结构体对齐: 1.自然对齐 struct 是一种复合数据类型,其构成元素既可以是基本数据类型(如int.long.float 等)的变量,也可以是一些复合数据类型(如array.s ...
- 深度学习方法(十二):卷积神经网络结构变化——Spatial Transformer Networks
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.机器学习技术感兴趣的同学加入. 今天具体介绍一个Google ...
- 洛谷 P2945 [USACO09MAR]沙堡Sand Castle 题解
题目传送门 大概思路就是把这两个数组排序.在扫描一次,判断大小,累加ans. #include<bits/stdc++.h> using namespace std; int x,y,z; ...
- IOS - Safari中click点击事件无效
做web移动端页面时,安卓端一点问题也没,发现在ios真机上点击事件无效,发现Safari下只有默认可点击的元素才click点击事件,像span div等元素是不具有点击事件的. 解决问题四种方式: ...
- 安装requests
requests包让Python程序能够轻松地向网站请求信息以及检查返回的响应.要安装requests,请执行类似于下面的命令: $ pip3 install --user requests http ...
- 五 Python基础 数据类型和变量
数据类型 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同的数据,需要定 ...
- java.lang.ClassCastException: android.widget.ImageButton异常处理
在调程序时总是出现异常关闭的现象,log显示: 03-26 07:58:09.528: E/AndroidRuntime(398): Caused by: java.lang.ClassCastExc ...
- vue-music 关于搜索历史本地存储
搜索历史 搜索过的关键词 保存在本地存储 localstorage 中,同时多个组件共享搜索历史数据,将数据存到vuex 中,初始值从本地缓存中取得对应key 的值,没有数据默认为空数组 点击搜索关键 ...
- bean的singleton(没有看到生命周期范围??)
4.5.1 The singleton scope Only one shared instance of a singleton bean is managed, and all requests ...
- ssm+RESTful bbs项目后端主要设计
小谈: 帖主妥妥的一名"中"白了哈哈哈.软工的大三狗了,也即将找工作,怀着丝丝忐忑接受社会的安排.这是第一次写博客(/汗颜),其实之前在学习探索过程中,走了不少弯路,爬过不少坑.真 ...