谈谈 final、finally、 finalize 有什么不一样?java
这三个简单来说就是卡巴斯基和巴基斯坦,有个基巴关系。。。安全
final 修饰的元素都不可改变,类不能继承,方法不能重写,变量不能修改。多线程
finally 在异常捕获中保证了除程序/线程关闭的状况外,块内的代码必须执行,一般用于关闭 JDBC 链接,unlock 锁等。post
finalize 是 Object 类的一个方法,将目标对象标记为特殊回收对象。因其不肯定性(不能肯定何时执行 GC)和下降 GC 效率(标记为特殊回收对象反而会阻碍 GC 流程),已在 JDK 中被标记为 deprecated。this
final List<String> strList = new ArrayList<>();
strList.add("Hello");
strList.add("world");
List<String> unmodifiableStrList = List.of("hello", "world");
unmodifiableStrList.add("again");
复制代码
strList是 final,但能够改变其内部元素内容,由于 final 保证了引用不更改,但引用的元素能够更改;unmodifiableStrList 是 immutable,不只建立了不可更改的引用,其元素内容也不可更改,因此在 调用 add 方法会抛异常。spa
immutable 一旦建立即不可改变,保证了线程安全,不用 synchroinzed 能够在多线程中使用,增长效率;缺点是在调用 get 方法后会 copy 一份,增长内存和 GC 负担。线程
在修改源数据 A 的时候额外复制一份源数据 B,在 B 上修改再将指针指向 B。设计
finalize 被设计为在被 GC 前调用,反而会阻碍 GC 处理,致使效率下降。3d
System.runFinalization()也不能确保 GC 何时执行。指针
资源用完即显式释放,或者利用资源池来尽可能重用。
java.lang.ref.Finalizer 会 swallow 异常。
private void runFinalizer(JavaLangAccess jla) {
// ... 省略部分代码
try {
Object finalizee = this.get();
if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
jla.invokeFinalize(finalizee);
// Clear stack slot containing this variable, to decrease
// the chances of false retention with a conservative GC
finalizee = null;
}
} catch (Throwable x) { }
super.clear();
}
复制代码
Cleaner 的实现利用了幻象引用(PhantomReference),使用 post-mortem 清理机制,更可靠和轻量。它有本身的运行线程,因此能够避免意外死锁等问题。(下期详解各类引用)
每一次成长,都想与你分享。