2020/07/18

[筆記] Effective Java #17 使可變性最小化

Effective Java 3rd 簡體中文版筆記 #17 使可變性最小化
Immutable class 就是實體不能修改的 class,所有訊息都在生成實體時設定,類似的 class 有 StringBigIntegerBigDecimal。建立 immutable class 時,需要注意以下幾點:
  1. 不提供任何會修改物件狀態的方法。
  2. 保證該 class 不會被繼承。避免其它 class 利用繼承破壞該 class 狀態,最簡單的方式為宣告為 final class 就無法被繼承。
  3. 所有的 field 皆為 final。
  4. 所有的 field 都是 private,降低不必要的訪問性。
  5. 如果有可變的 (mutable) field,必須確保調用者是無法取得 field 的引用,也不要將外部傳入的引用當作 field,應使用保護性拷貝 (defensive copy)
下面是複數 Complex 的程式碼,plussubtract 方法都是回傳新的實體,這種作法稱為 functional approach。
public final class Complex {
    private final double re;
    private final double im;
    public Complex(double re, double im) {
        this.re = re;
        this.im = im;
    }

    public double realPart() { return re; }
    public double imaginaryPart() { return im; }
    public Complex plus(Complex c) {
        return new Complex(re + c.re, im + c.im);
    }
    public Complex subtract(Complex c) {
        return new Complex(re - c.re, im - c.im);
    }
    ...
}
Immutable class 本質是 thread-safe 沒有 concurrent 問題,自然就不需要同步,理所當然可以共用。它的缺點為每一個不同的內容皆需要產生新物件,針對頻繁使用的內容,應提供 public static final 的常數,減少物件生成的數量。同時 immutable class 在作大量操作時,會產生非常多的中繼物件,它們的生命週期相當短,也沒有機會被重複使用,有可能會引起效能問題。解決方法為 class 應該提供方法,幫助相關操作或是提供 mutable class 來協助,像是 StringBuilderString 即為一例子。
public static final Complex ZERO = new Complex(0, 0);
public static final Complex ONE = new Complex(1, 0);
public static final Complex I = new Complex(0, 1);
Immutable class 是否一定為 final class,裡面的 field 是否一定為 final field? 可以提供 static factory method,然後使用 private constructor,同時亦可在 factory 中提供 buffer 機制,重複利用相同的物件。至於是否需定義為 final field,不一定,若是該 field 設定成本較昂貴,又不一定會用到,那就可以在方法被調用的第一次時在設定即可。
private Complex(int r, int i) {
    this.r = r;
    this.i = i;
}

public static Complex newComplex(int r, int i) { 
    return new Complex(r, i); 
}
如果 immutable class 實作 Serializable 介面,且 field 包含可變性的引用,就必須提供 readResolve 或是 readObject,不然會從 immutable class 中創建出 mutable 物件。即使在 mutable class 中,也應盡量限制它的可變性,這樣能降低出錯率,也更容易分析。不要在 constructor 及 public static factory 之外處,提供初始化方法。

轉載請註明原文網址 https://cookieandcoketw.blogspot.com/2020/07/effective-java-17-immutable.html

沒有留言:

張貼留言