以下转自:孙卫琴《Java面向对象编程 》
11.4.3 对象的finalize()方法简介
当垃圾回收器将要释放无用对象的内存时,先调用该对象的finalize()方法。如果在程序终止之前垃圾回收器始终没有执行垃圾回收操作,那么垃圾回收器将始终不会调用无用对象的finalize()方法。在Java的Object祖先类中提供了protected类型的finalize()方法,因此任何Java类都可以覆盖finalize()方法,在这个方法中进行释放对象所占的相关资源的操作。
Java虚拟机的垃圾回收操作对程序完全是透明的,因此程序无法预料某个无用对象的finalize()方法何时被调用。另外,除非垃圾回收器认为程序需要额外的内存,否则它不会试图释放无用对象占用的内存。换句话说,以下情况是完全可能的:一个程序只占用了少量内存,没有造成严重的内存需求,于是垃圾回收器没有释放那些无用对象占用的内存,因此这些对象的finalize()方法还没有被调用,程序就终止了。
程序即使显式调用System.gc()或Runtime.gc()方法,也不能保证垃圾回收操作一定执行,因此不能保证无用对象的finalize()方法一定被调用。
11.4.4 对象的finalize()方法的特点
对象的finalize()方法具有以下特点:
垃圾回收器是否会执行该方法及何时执行该方法,都是不确定的。
finalize()方法有可能使对象复活,使它恢复到可触及状态。
垃圾回收器在执行finalize()方法时,如果出现异常,垃圾回收器不会报告异常,程序继续正常运行。
下面结合一个具体的例子来解释finalize()方法的特点。例程11-13的Ghost类是一个带实例缓存的不可变类,它的finalize()方法能够把当前实例重新加入到实例缓存ghosts中。
例程11-13 Ghost.java
运行以上Ghost类的main()方法,一种可能的打印结果为:
Ghost@3179c3
execute finalize
Ghost@3179c3
以上程序创建了3个对象:1个Ghost对象、1个常量字符串“IAmBack”及1个HashMap对象。当程序执行完main()方法的第③行时,内存中引用变量与对象之间的关系如图11-9所示。
图11-9 Ghost对象与其他对象及引用变量的关系
当执行完第④行时,ghost变量被置为null,此时Ghost对象依然被ghosts属性间接引用,因此仍然处于可触及状态。当执行完第⑤行时,Ghost对象的引用从HashMap对象中删除,Ghost对象不再被程序引用,此时进入可复活状态,即变为无用对象。
第⑥行调用System.gc()方法,它能提高垃圾回收器尽快执行垃圾回收操作的可能性。假如垃圾回收器线程此刻获得了对CPU的使用权,它将调用Ghost对象的finalize()方法。该方法把Ghost对象的引用又加入到HashMap对象中,Ghost对象又回到可触及状态,垃圾回收器放弃回收它的内存。执行完第⑧行,ghost变量又引用这个Ghost对象。
假如对finalize()做一些修改,使它抛出一个异常:
protected void finalize()throws Throwable{
ghosts.put(name,this);
System.out.println("execute finalize");
throw new Exception("Just Test");
}
程序的打印结果不变。由此可见,当垃圾回收器执行finalize()方法时,如果出现异常,垃圾回收器不会报告异常,也不会导致程序异常中断。
假如在程序运行中,垃圾回收器始终没有执行垃圾回收操作,那么Ghost对象的finalize()方法就不会被调用。读者不妨把第⑥行的System.gc()和第⑦行的Thread.sleep(3000)方法注释掉,这样更加可能导致finalize()方法不会被调用,此时程序的一种可能的打印结果为:
Ghost@3179c3
Ghost@310d42
从以上打印结果可以看出,由于Ghost对象的finalize()方法没有被执行,因此这个Ghost对象在程序运行期间始终没有复活。当程序第二次调用Ghost.getInstance("IAmBack")方法时,该方法创建了一个新的Ghost对象。
值得注意的是,以上例子仅仅用于演示finalize()方法的特性,在实际应用中,不提倡用finalize()方法来复活对象。可以把处于可触及状态的对象比做活在阳间的人,把不处于这个状态的对象(无用对象)比做到了阴间的人。程序所能看见和使用的是阳间的人,假如阎王经常悄悄地让几个阴间的人复活,使他们在程序毫不知情的情况下溜回阳间,这只会扰乱程序的正常执行流程。
11.4.5 比较finalize()方法和finally代码块
在Object类中提供了finalize()方法,它的初衷是用于在对象被垃圾回收器回收之前,释放所占用的相关资源,这和try…catch…finally语句的finally代码块的用途比较相似。但由于垃圾回收器是否会执行finalize()方法及何时执行该方法,都是不确定的,因此在程序中不能用finalize()方法来完成同时具有以下两个特点的释放资源的操作。
必须执行。
必须在某个确定的时刻执行。
具有以上特点的操作更适合于放在finally代码块中。此外,可以在类中专门提供一个用于释放资源的公共方法,最典型的就是java.io.InputStream和java.io.OutputStream类的close()方法,它们用于关闭输入流或输出流。当程序中使用了一个输入流时,在结束使用前应该确保关闭输入流。
InputStream in;
try{
InputStream in=new FileInputStream("a.txt");
…
}catch(IOException e){
…
}finally{
try{in.close();}catch(IOException e){…}
}
在多数情况下,应该避免使用finalize()方法,因为它会导致程序运行结果的不确定性。在某些情况下,finalize()方法可用来充当第二层安全保护网,当用户忘记显式释放相关资源时,finalize()方法可以完成这一收尾工作。尽管finalize()方法不一定会被执行,但是有可能会释放资源,这总比永远不会释放资源更安全。
可以用自动洗衣机的关机功能来解释finalize()方法的用途。自动洗衣机向用户提供了专门的关机按钮,这相当于AutoWasher类的close()方法,假如用户忘记关机,相当于忘记调用AutoWasher对象的close()方法,那么自动洗衣机会在洗衣机停止工作后的1个小时内自动关机,这相当于调用finalize()方法。当然,这个例子不是太贴切,因为如果用户忘记关机,洗衣机的自动关机操作总会被执行。
<!-- page -->
分享到:
相关推荐
MATLAB实验一二 数值计算
Java毕业设计-ssm基于SSM的英语学习网站的设计与实现演示录像(高分期末大作业)
平安保险-智富人生A的计算
MATLAB实验五六 图像相关应用
AUTOSAR_SRS_FreeRunningTimer.pdf
onnxruntime-1.7.1-cp39-cp39-linux_armv7l.whl.zip
qwen2 colab代码
885 - Space Scooter.mpd
该资源是软考-信息系统项目管理师 高级考试 相关的论文资源,《论项目整体管理》。项目基于本人在实际的工作中的最佳实践,以软件工程实施为背景,从 制定项目章程、制定项目管理计划、指导与管理项目工作、管理项目知识、监控项目工作、实施整体变更控制、结束项目或阶段的角度介绍了项目资源管理的方法论。 理论框架基于最新的 PMBOK 第6版,核心理念是项目管理是一个综合性工程,不仅要重点关注项目范围、进度、成本、质量四要素,更要关注整体管理、资源管理、风险管理、干系人管理、沟通管理、采购管理、绩效域管理等。在项目新兴实践方面还要注意与敏捷管理的结合,因为现在的大型项目更多使用的是混合型开发模式,主体功能采用预测型生命周期,而分支功能或非主体功能可能采用敏捷生命周期,只有综合运用领导力技能和项目管理的最佳实践,才能使项目最终走向成功。
AUTOSAR_SWS_IntrusionDetectionSystemManager.pdf
python模块onnxruntime版本
AUTOSAR_SRS_SAEJ1939.pdf
AUTOSAR_SRS_CryptoStack.pdf
瑞士轮
cfx
纸片战争Beta压缩试行代码
python模块onnxruntime版本
Java毕业设计-ssm汽车租赁管理演示录像(高分期末大作业)
树状数组-20-子查询.ev4.rar
此资源为完整项目部署后演示效果视频,可参考后再做项目课设决定。 包含:项目源码、数据库脚本、项目说明等,有论文参考,该项目可以直接作为毕设使用。 技术实现: 后台框架:SpringBoot框架 或 SSM框架 数据库:MySQL 开发环境:JDK、IDEA、Tomcat 项目都经过严格调试,确保可以运行! 博主可有偿提供毕设相关的技术支持 如果您的开发基础不错,可以在此代码基础之上做改动以实现更多功能。 其他框架项目设计成品不多,请根据情况选择,致力于计算机专业毕设项目研究开发。