不可变中的可变项
Mutable items in Immutable
当我们使用 Immutable objects library, how can we handle mutable members (e.g. j.u.Date)?
创建不可变 classes 时
注意:这 不是 关于 java 日期 class 并且与 不可变对象 完全相关java 将生成一些代码的库!
示例:
@Value.Immutable
public interface MyImmutableClass {
Date creationDateTime();
}
有没有办法覆盖 getter,使其成为 returns 的副本?
public Date creationDateTime() {
return new Date(creationDateTime.getTime());
}
Is there a way to override the getter, so that it returns a copy?
很像你在那里写的:
public Date creationDateTime() {
return new Date(creationDateTime.getTime());
}
(就像上面评论中指出的 khelwood)。
但是,如果您想避免 class 中 creationDateTime
的意外突变,请考虑将毫秒存储为 final long
:
private final creationDateTimeMillis;
public Date creationDateTime() {
return new Date(creationDateTimeMillis);
}
而即使 Date
是 final
,您也可以调用 Date.setTime()
,从而改变内部状态,您不能重新分配 creationDateTimeMillis
。
您可以制作生成的方法 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
来自我在 Immutables issue tracker I learned that the cleanest way to handle mutable objects is to use a custom encoding annotation 中的问题。
我创建了一个小型开源项目 tmtron-immutables encoding 来为 java.util.Date
class 创建这样的注释。对于想要创建自定义编码的任何人来说,这应该是一个很好的起点。
然后你可以直接使用你的可变 class(例如 java.util.Date
)作为属性,并且仍然获得与不可变属性(如 String、long 等)相同的不变性保证
@Value.Immutable
@DateEncodingEnabled
public interface ValueObject {
Date creationDate();
}
@DateEncodingEnabled
注释将确保只有 Date 对象的不可变 long 值存储在 ImmutableValueObject
class.
当我们使用 Immutable objects library, how can we handle mutable members (e.g. j.u.Date)?
创建不可变 classes 时注意:这 不是 关于 java 日期 class 并且与 不可变对象 完全相关java 将生成一些代码的库!
示例:
@Value.Immutable
public interface MyImmutableClass {
Date creationDateTime();
}
有没有办法覆盖 getter,使其成为 returns 的副本?
public Date creationDateTime() {
return new Date(creationDateTime.getTime());
}
Is there a way to override the getter, so that it returns a copy?
很像你在那里写的:
public Date creationDateTime() {
return new Date(creationDateTime.getTime());
}
(就像上面评论中指出的 khelwood)。
但是,如果您想避免 class 中 creationDateTime
的意外突变,请考虑将毫秒存储为 final long
:
private final creationDateTimeMillis;
public Date creationDateTime() {
return new Date(creationDateTimeMillis);
}
而即使 Date
是 final
,您也可以调用 Date.setTime()
,从而改变内部状态,您不能重新分配 creationDateTimeMillis
。
您可以制作生成的方法 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
来自我在 Immutables issue tracker I learned that the cleanest way to handle mutable objects is to use a custom encoding annotation 中的问题。
我创建了一个小型开源项目 tmtron-immutables encoding 来为 java.util.Date
class 创建这样的注释。对于想要创建自定义编码的任何人来说,这应该是一个很好的起点。
然后你可以直接使用你的可变 class(例如 java.util.Date
)作为属性,并且仍然获得与不可变属性(如 String、long 等)相同的不变性保证
@Value.Immutable
@DateEncodingEnabled
public interface ValueObject {
Date creationDate();
}
@DateEncodingEnabled
注释将确保只有 Date 对象的不可变 long 值存储在 ImmutableValueObject
class.