2014-03-19 138 views
0

假設我創建了一個具有可變類參考地址的不可變類Employee。我們如何用場景創建不可變的類。參考可變類的不可變類

我只是指這個鏈接click here。我不明白這一點:

不要共享對可變對象的引用。切勿將引用 存儲到傳遞給構造函數的外部可變對象;如有必要, 創建副本,並存儲對副本的引用。同樣,必要時創建 內部可變對象的副本,以避免 在您的方法中返回原件。

+1

顯示一個小例子,複製,你試圖描述的情況,強調所有涉及對象的創建和情況下,您做或不想要可變性。 – reto

+0

請正確解釋問題。問題不明確 –

+1

是的,我知道這個類不是不可變的,有可能使這個類不可變嗎? –

回答

1

你不能,不能沒有打破Address類的合同。

相反,您可以創建一個新類,我將其稱爲ImmutableAddress,並在其構造函數中接受Address,並從中獲取相關信息,爲該信息公開獲取者,但不提供setter。 (重要的是,您不要只存儲Address;您必須從中獲取信息並存儲該信息,因爲您不能相信任何不會修改您提供的內容的情況)。然後在Employee上使用ImmutableAddress而不是Address

現在,話雖如此,可悲的事實是,你看到班級合同與運行時異常相當規律的破壞。你這樣做的方式是子類Address,並使其所有setter拋出一個運行時異常,然後通過引用Address構造你的子類。但這是一個破解,更好地創建新的,真正不可改變的類。

0

您需要創建Address類的不可變副本,並在Employee類中使用該副本。例如:

public final class ImmutableAddress 
{ 
    private final String street; 

    public ImmutableAddress(final Addres addr) 
    { 
     Objects.checkNotNull(addr, "null arguments not accepted"); 
     street = addr.getStreet(); 
    } 

    // Alternate, static constructor 
    public static ImmutableAddress from(final Address addr) 
    { 
     return new ImmutableAddress(addr); 
    } 

    public String getStreet() { return street; } 
} 

然後在Employee構造函數,你會怎麼做:

private final ImmutableAddress addresss; 

public Employee(final Address addr) 
{ 
    address = ImmutableAddress.from(addr); 
} 
4

如果你想封裝可變對象爲不可變的一個,那麼你需要:

  • 創建可變對象的副本(即通過拷貝構造函數,克隆,序列化/反序列化等);永遠不要將引用存儲到原始可變對象中。
  • 永遠不會返回可變對象。如果您必須,則返回該對象的副本。
  • 避免方法可以改變的可變對象

參考:A Strategy for Defining Immutable Objects - The Java tutorials