1. 程式人生 > >總結final、finally、 finalize

總結final、finally、 finalize

Q1 final、finally、 finalize 有哪些不同

  1. final 可以用來修飾類、方法、變數,分別有不同的意義。final 修飾的 class 代表不可以繼承擴充套件,final 的變數是不可以修改的,而 final 的方法也是不可以重寫的(override)。
  2. finally 則是 Java 保證重點程式碼一定要被執行的一種機制。我們可以使用 try-finally 或者 try-catch-finally 來進行類似關閉 JDBC 連線、保證 unlock 鎖等動作。
  3. finalize 是基礎類 java.lang.Object 的一個方法,它的設計目的是保證物件在被垃圾收集前完成特定資源的回收。finalize 機制現在已經不推薦使用,並且在 JDK 9 開始被標記為 deprecated。

Q2 final最佳實踐:

  1. 我們可以將方法或者類宣告為 final,這樣就可以明確告知別人,這些行為是不許修改的。
  2. 使用 final 修飾引數或者變數,也可以清楚地避免意外賦值導致的程式設計錯誤,甚至,有人明確推薦將所有方法引數、本地變數、成員變數宣告成 final。
  3. final 變數產生了某種程度的不可變(immutable)的效果,所以,可以用於保護只讀資料,尤其是在併發程式設計中,因為明確地不能再賦值 final 變數,有利於減少額外的同步開銷,也可以省去一些防禦性拷貝的必要。

Q3 final需要注意的點

final 不是 immutable,對於物件和列表等需要final資料時,需要特殊處理 1. 將class自身設定為final,防止擴充套件 2. 將內部屬性定義成final或者私有化setter方法 3. 構造變數是採用深拷貝 4. getter採用copyOnWriter原則

CopyOnWrite 容器即寫時複製容器,原理就是當我們往一個容器新增元素時,不直接往當前容器新增,而是先將當前容器進行Copy,複製出新的容器,然後往新的容器進行新增元素,新增好之後,再將原來的容器引用指向新的容器。 這樣的好處就是,我們可以對CopyOnWrite容器進行併發的讀,也不需要加鎖,因為當前容器不會新增任何新的元素。 CopyOnWrite容器也是一個讀寫分離的思想

Q4 finalize的略根性

finalize常常跟GC聯絡到一起,在GC前被呼叫,若有耗時邏輯會影響GC效率,可能會導致OOM。

Q5 finalize的替代機制:

Java 平臺目前在逐步使用 java.lang.ref.Cleaner 來替換掉原有的 finalize 實現。

Cleaner 的實現利用了幻象引用(PhantomReference),這是一種常見的所謂 post-mortem 清理機制。我會在後面的專欄系統介紹 Java 的各種引用,利用幻象引用和引用佇列,我們可以保證物件被徹底銷燬前做一些類似資源回收的工作,比如關閉檔案描述符(作業系統有限的資源),它比 finalize 更加輕量、更加可靠。

public class CleaningExample implements AutoCloseable {
        // A cleaner, preferably one shared within a library
        private static final Cleaner cleaner = <cleaner>;
        static class State implements Runnable { 
            State(...) {
                // initialize State needed for cleaning action
            }
            public void run() {
                // cleanup action accessing State, executed at most once
            }
        }
        private final State;
        private final Cleaner.Cleanable cleanable
        public CleaningExample() {
            this.state = new State(...);
            this.cleanable = cleaner.register(this, state);
        }
        public void close() {
            cleanable.clean();
        }
    }