简体   繁体   English

不可变的可变项

[英]Mutable items in Immutable

When we create immutable classes using the Immutable objects library, how can we handle mutable members (eg juDate )? 当我们使用Immutable对象库创建不可变类时,我们如何处理可变成员(例如juDate )?

NOTE: this is not about the java Date class and totally related to the Immutable Objects java library which will generate some code! 注意:这不是关于java Date类, 而是Immutable Objects java库完全相关,它将生成一些代码!

Example: 例:

@Value.Immutable
public interface MyImmutableClass {
    Date creationDateTime();
}

Is there a way to override the getter, so that it returns a copy? 有没有办法覆盖getter,以便它返回一个副本?

public Date creationDateTime() {
    return new Date(creationDateTime.getTime());
}

Is there a way to override the getter, so that it returns a copy? 有没有办法覆盖getter,以便它返回一个副本?

Pretty much like you've written it there: 就像你在那里写的一样:

public Date creationDateTime() {
    return new Date(creationDateTime.getTime());
}

(like khelwood pointed out in the comments above). (就像凯尔伍德在上面的评论中指出的那样)。

However, if you want to avoid accidental mutation of creationDateTime inside your class, consider just storing the millis as a final long : 但是,如果您想避免在类中意外突变creationDateTime ,请考虑将millis存储为final long

private final creationDateTimeMillis;

public Date creationDateTime() {
    return new Date(creationDateTimeMillis);
}

Whereas you can call Date.setTime() even if the Date is final , thus mutating the internal state, you can't reassign creationDateTimeMillis . 即使Datefinal ,也可以调用Date.setTime() ,从而改变内部状态,您无法重新分配creationDateTimeMillis

You can make the generated method protected and serve the field only from a cloning getter method: 您可以使生成的方法protected并仅从克隆getter方法提供字段:

@Value.Immutable
public abstract class WrapMutable {
    protected abstract Date timestamp();

    public Date getTimestamp() {
        return new Date(timestamp().getTime());
    }
}

All usage of the field is then through its copy-getter, while the timestamp() method is only used to define the setter in the builder: 然后,该字段的所有用法都是通过其copy-getter,而timestamp()方法仅用于在构建器中定义setter:

WrapMutable obj = ImmutableWrapMutable.builder().timestamp(new Date()).build();
System.out.println(obj.getTimestamp());
System.out.println(obj.timestamp()); // Error: timestamp() has protected access in WrapMutable

From my question in the Immutables issue tracker I learned that the cleanest way to handle mutable objects is to use a custom encoding annotation . 根据我在Immutables问题跟踪器中的问题,我了解到处理可变对象的最简洁方法是使用自定义编码注释

I've created a little open source project tmtron-immutables encoding to create such an annotation for the java.util.Date class. 我已经创建了一个小的开源项目tmtron-immutables编码来为java.util.Date类创建这样的注释。 This should be a good starting point for anyone who wants to create a custom encoding. 对于想要创建自定义编码的任何人来说,这应该是一个很好的起点。

Then you can directly use your mutable class (eg java.util.Date ) as attribute and still get the same immutability guarantee as for immutable attributes (like String, long, etc.) 然后你可以直接使用你的可变类(例如java.util.Date )作为属性,并且仍然获得与不可变属性(如String,long等)相同的不变性保证。

@Value.Immutable
@DateEncodingEnabled
public interface ValueObject {
    Date creationDate();
}

The @DateEncodingEnabled annotation will make sure that only the immutable long value of the Date object is stored in the ImmutableValueObject class. @DateEncodingEnabled注释将确保只有Date对象的不可变long值存储在ImmutableValueObject类中。

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

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