简体   繁体   English

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

[英]How to update a field in a immutable object

Supposing the following class: 假设以下类别:

@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;
 }

}

Once we have built an object of this class, 一旦建立了此类的对象,

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

and once we have finish doing some operations with it, 一旦完成操作,

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

it is expected to get an identifier from somewhere (a remote service, for instance) and attach it to the message . 期望从某个地方(例如,远程服务)获取identifier并将其附加到message But, if I do something like this: 但是,如果我做这样的事情:

myMessageObject.setIdentifier(identifier);

I supposedly breaking the immutability capability of the object. 我应该打破了对象的不变性能力。 If so, how is the best way to update the identifier field avoiding to do a new constructor call (so creating a new object)? 如果是这样,那么更新identifier字段的最佳方法是如何避免执行新的构造函数调用(从而创建一个新对象)?

So the problem is just because you want to log some stuff first? 所以问题仅仅是因为您想先记录一些东西? Can't you do that after you've constructed the object? 构造对象后不能这样做吗?

Alternatively, you can use the builder pattern, with something like this. 或者,您可以使用构建器模式,类似这样。 Note the final instance fields - instances of this class will be immutable even without the annotation. 请注意最终实例字段-即使没有注释,此类的实例也将是不可变的。

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

You can then incrementally build the content of your object. 然后,您可以逐步构建对象的内容。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM