为什么 Joda 对象是不可变的?

2022-09-03 13:05:25

我读过,对于小于7的Java版本,Joda Time对象比Java的内置版本更可靠。一个被引用的原因是Joda对象是不可变的。为什么这是有益的?如果我想更改Joda DateTime对象的年,小时和时区,我需要制作三个副本!


答案 1

如果我想更改Joda DateTime对象的年,小时和时区,我需要制作三个副本!

是的,确实如此。或者,当然,您可以使用旧对象中您喜欢的所有字段来创建个新对象。

这是一件彻头彻尾的好事 - 因为这意味着当你想依靠一个不改变的对象时,它不会改变。请考虑以下伪代码:

private static final Instant EARLIEST_ALLOWED_ARTICLE = ...;

private Instant creationTimestamp;

public Article(Instant creationTimestamp, ...) {
    if (creationTimestamp.isBefore(EARLIEST_ALLOWED_ARTICLE)) {
        throw new IllegalArgumetnException(...);
    }
    this.creationTimestamp = creationTimestamp;
    ...
}

这很好,因为它是不可变的。如果它是可变的,则构造函数中的验证将毫无价值 - 除非您在此时创建了防御性副本。Instant

根据我的经验,您希望传递引用并知道值不会比您希望实际对现有对象进行更改的更改更多,因此不可变性导致更少的错误(对于可变对象,您可以忘记获取副本,然后任何验证都是无用的),并且创建的副本更少。

基本上,它允许您在本地推理代码,而无需复制您接受和存储的所有内容,或者返回到其他代码。当只有你的代码可以更改对象的状态时,计算出随着时间的推移会发生什么要简单得多。

Joda Time实际上有些失败,因为它具有可变和不可变的类型 - 如果你只是编程到接口(例如),那么你就没有得到这些保证。这就是为什么在野田时代,我让所有类型都真正不可变。ReadableInstant

出于兴趣,您是否希望可变?如果没有,请尝试考虑两种方案之间是否存在真正的差异。String


答案 2

最简单的答案是,一旦你创建了一个对象,你就知道它不能改变。这意味着您不会遇到数据以意外方式更改的情况(可能在代码的其他部分或不同的线程中)。

这使得对象的行为更加可预测和可靠。


推荐