Java 如何更新不可变对象中的字段

Java 如何更新不可变对象中的字段,java,oop,immutability,Java,Oop,Immutability,假设以下类别: @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

假设以下类别:

@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());
它需要从某处(例如远程服务)获取
标识符
,并将其附加到
消息
。但是,如果我这样做:

myMessageObject.setIdentifier(identifier);

我假定破坏了对象的不变性。如果是这样,那么更新
标识符
字段的最佳方法是如何避免执行新的构造函数调用(从而创建新对象)?

那么问题只是因为您想先记录一些内容?你不能在构建完对象后再这样做吗

或者,您可以使用构建器模式,类似于这样。注意final instance字段-即使没有注释,该类的实例也是不可变的

@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();

如果您可以更新文件,它将不再保持不变。为什么您想要一个注释为
@immutable
的可变对象。我想在尝试这样的事情之前,您应该先考虑一下您的设计。我想要一个不可变对象,但我需要一种方法将远程生成的标识符附加到不可变对象包含的消息。根据到目前为止收到的答案,我担心这是不可能的,除非我构建一个新对象并将标识符作为构造函数参数传递。您可以添加一个静态方法
newMessageObject(msg)
,记录消息,确定时间戳和标识符,并返回构造函数获取所有这3个参数的结果。“log”操作只是一个示例。我不需要这样做,但我认为这是一种说明如何访问对象状态的方法。
@Immutable
注释不会使类不可变,只是简单地提示编译器和其他工具它应该不可变。我知道这一点,但我的观点是,尽管有注释,对象实际上并不是不可变的。这是基于存在
setIdentifier()
,这在原始代码中提到但未显示。