2015-05-04 64 views
1

假設下面的類更新字段:如何在不可變對象

@Immutable 
public final MyMessageClass { 

private String message; 
private Date dateLastChange; 
private String identifier; 

public MyClass(final String message){ 
    this.message = message; 
    dataLastChange = new Date(); 
} 

public Date lastChange() { 
    return new Date(dateLastChange.getTime()); 
} 

public String messageValue(){ 
    return message; 
} 

} 

一旦我們建立了這個類的一個對象,

MyMessageClass myMessageObject = new MyMessageClass("Once upon a time ..."); 

,一旦我們完成做一些操作與它,

logger.info("The message is{}",myMessageObject.messageValue()); 
logger.info("The last change was done on {}",myMessageObject.lastChange()); 

它預計從某個地方得到identifier(遠程服務,爲ins tance)並將其附加到message。但是,如果我做這樣的事情:

myMessageObject.setIdentifier(identifier); 

我理應打破對象的不變性能力。如果是這樣,請更新identifier字段以避免執行新的構造函數調用(創建新對象)的最佳方法是什麼?

+2

如果你可以更新提交它不會永遠不會改變。 – Saif

+1

爲什麼你想要一個註解爲@ @ Immutable'的* mutable *對象。我想你在嘗試這樣的事情之前首先考慮你的設計。 –

+0

我想要一個不可變的對象,但我需要一種將遠程生成的標識符附加到不可變對象包含的消息的方法。根據收到的答案,直到沒有,恐怕這是不可能的,除非我建立一個新的對象,並將標識符作爲構造函數參數傳遞。 –

回答

2

所以這個問題只是因爲你想先登錄一些東西?你在構造對象之後不能這樣做嗎?

或者,您可以使用類似於此的構建器模式。注意最終的實例字段 - 即使沒有註釋,這個類的實例也是不可變的。

@Immutable 
public final MyMessageClass { 

    private final String message; 
    private final Date dateLastChange; 
    private final String identifier; 

    public MyClass(final MyMessageClass.Builder builder){ 
     this.message = builder.message; 
     this.dataLastChange = builder.dataLastChange; 
     this.identifier = builder.identifier; 
    } 

    public Date lastChange() { 
     return new Date(dateLastChange.getTime()); 
    } 

    public String messageValue(){ 
     return message; 
    } 

    public String identifier(){ 
     return identifier; 
    } 

    public static final class Builder { 
     private String message; 
     private final Date dateLastChange = new Date(); 
     private String identifier; 

     public Builder message(final String message) { 
      this.message = message; 
      return this; 
     } 

     public String message() { 
      return message; 
     } 

     public Builder identifier(final String identifier) { 
      this.identifier = identifier; 
      return this; 
     } 

     public String identifier() { 
      return identifier; 
     } 

     public Date lastChange() { 
      return new Date(dateLastChange.getTime()); 
     } 

     public MyMessageClass build() { 
      return new MyMessageClass(this); 
     } 
    } 
} 

然後,您可以增量構建對象的內容。

MyMessageClass.Builder builder = new MyMessageClass.Builder().message("Once upon a time ..."); 
logger.info("The message is{}", builder.message()); 
logger.info("The last change was done on {}",builder.lastChange()); 
String identifier = // get the identifier from somewhere 
MyMessageClass message = builder.identifier(identifier).build(); 
+0

@ @ Immutable註解不會使類不可變,而只是提示編譯器和其他工具它應該是不可變的。 –

+0

我意識到這一點,但我的觀點是,儘管有註釋,對象並不是實際上不可變的。這是基於'setIdentifier()'存在的,這是提到但在原始代碼中沒有顯示。 –