不可变

时间:2017-02-20 13:20:56

标签: java immutability immutables-library

当我们使用Immutable objects库创建不可变类时,我们如何处理可变成员(例如j.u.Date)?

注意:这是关于java Date类的,并且与不可变对象 java库完全相关,它将生成一些代码!

示例:

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

有没有办法覆盖getter,以便它返回一个副本?

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

3 个答案:

答案 0 :(得分:1)

  

有没有办法覆盖getter,以便它返回一个副本?

非常像你在那里写的那样:

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

(如上文评论中指出的khelwood)。

但是,如果您想避免课堂内creationDateTime的意外变异,请考虑将millis存储为final long

private final creationDateTimeMillis;

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

即使Date.setTime()Date,您也可以致电final,从而改变内部状态,但您无法重新分配creationDateTimeMillis

答案 1 :(得分:1)

您可以生成方法protected并仅使用克隆getter方法提供字段:

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

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

该字段的所有用法都是通过其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

答案 2 :(得分:1)

根据Immutables issue tracker中的问题,我了解到处理可变对象的最简洁方法是使用custom encoding annotation

我已经创建了一个小型开源项目tmtron-immutables encoding来为java.util.Date类创建这样的注释。对于想要创建自定义编码的任何人来说,这应该是一个很好的起点。

然后你可以直接使用你的可变类(例如java.util.Date)作为属性,并且仍然获得与不可变属性(如String,long等)相同的不变性保证。

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

@DateEncodingEnabled注释将确保只有Date对象的不可变long值存储在ImmutableValueObject类中。