談談 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 清理機制,更可靠和輕量。它有本身的運行線程,因此能夠避免意外死鎖等問題。(下期詳解各類引用)
每一次成長,都想與你分享。