Java核心技术 3讲

谈谈final、finally、finalize有什么不同?

这三个就像巴基斯坦、巴勒斯坦、卡巴斯基的关系一样,有个基巴关系。

final

final
|属性|作用|
|:--:|:--:|
|class|不可继承扩展|
|变量|不可修改|
|方法|不可重写|

finally

java保证重点代码一定要被执行的一种机制。try-finally或者try-catch-finally来进行类似关闭JSBC连接、保证unlock锁等动作。

finalize

finalize是基础类java.lang.Object的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。finalize机制现在已经不推荐使用,并且人在JDK9开始被标记为deprecated。

  1. 注意,final 不是 immutable!
 final List<String> strList = new ArrayList<>();
 strList.add("Hello");
 strList.add("world");  
 List<String> unmodifiableStrList = List.of("hello", "world");
 unmodifiableStrList.add("again");

final只能约束strList这个引用不可以被赋值,但是strList对象行为不被final影响,添加元素等操作是完全正常的。
如果我们真的希望对象本身是不可变的,那么需要相应的类支持不可变的行为。

Immutable 在很多场景是非常棒的选择,某种意义上说,Java 语言目前并没有原生的不可变支持,如果要实现 immutable 的类,我们需要做到:
1.将 class 自身声明为 final,这样别人就不能扩展来绕过限制了。
2.将所有成员变量定义为 private 和 final,并且不要实现 setter 方法。
3.通常构造对象时,成员变量使用深度拷贝来初始化,而不是直接赋值,这是一种防御措施,因为你无法确定输入对象不被其他人修改。
4.如果确实需要实现 getter 方法,或者其他可能会返回内部状态的方法,使用 copy-on-write 原则,创建私有的 copy。

2.finalize真的那么不堪?
finalize的执行是和垃圾手机关联在一起的,一旦实现了非空的finalize方法,就会导致相应对象回收呈现数量级上的变慢,有人专门做过benchmark,大概就是40~50倍的下降。
因为finalize被设计成在对象被垃圾收集前调用,这就意味着实现了finalize方法 的对象是个“特殊公民”,jvm要对它进行额外处理。finalize本质上成为了快速回收的阻碍者,可能导致你的对象经过多个垃圾收集周期才能够被回收。
System.runFinalization()
不可预测、不能保证、不能指望。
实践中,因为finalize拖慢垃圾收集,导致大量对象堆积,也是一种典型的导致OOM的原因。
资源用完即显示释放,或者利用资源池来尽量重用。

3.有什么机制可以替换finalize
java.lang.ref.Cleaner替换原来的finalize实现。Cleaner的实现利用了幻象引用(PhantomReference),这是一种常见的所谓post-mortem清理机制。

本文链接:

https://heyzen.club/index.php/J/77.html
1 + 5 =
快来做第一个评论的人吧~