2

当我们使用不可变对象库创建不可变类时,我们如何处理可变成员(例如juDate)?

注意:这与java Date 类无关,与不可变对象java 库完全相关,后者将生成一些代码!

例子:

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

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

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

3 回答 3

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()即使Dateis也可以调用final,从而改变内部状态,但不能重新分配creationDateTimeMillis

于 2017-02-20T13:26:38.490 回答
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
于 2017-02-20T14:08:30.850 回答
1

从我在不可变问题跟踪器中的问题中,我了解到处理可变对象的最简洁方法是使用自定义编码注释

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

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

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

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

于 2017-02-25T15:13:00.007 回答