2015-05-04 2 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 откуда-то (удаленный сервис для модулей tance) и прикрепите его к message. Но если я сделаю что-то вроде этого:

myMessageObject.setIdentifier(identifier); 

Я предположительно нарушаю неизменяемость объекта. Если да, то как наилучшим образом обновить поле identifier, избегая выполнения нового вызова конструктора (чтобы создать новый объект)?

+2

Если вы можете обновить поданный, он больше не останется неизменным. – Saif

+1

Почему вы хотите * изменяемый * объект, который аннотируется как '@ Immutable'. Я думаю, вы сначала подумали о своем дизайне перед тем, как попробовать такие вещи. –

+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()', который упоминается, но не показан в исходном коде. –

Смежные вопросы