为什么实例变量是最终的?

Why instance variable to be final?

我阅读了 this question 有关不可变对象的内容,并留下了有关不可变对象和最终字段的问题:

为什么我们需要不可变 class 中的实例变量是最终的?

例如,考虑这个不可变的 class:

public final class Immutable 

{

  private final int someVal;

  public Immutable(int someVal)
 {

    this.someVal= someVal;
  }

  public int getVal() {

    return val;
}

}

如果上述代码中没有set方法,实例变量只在构造函数中设置,为什么要求实例变量声明为final?

在不可变 class 中,您无法更改其 property/field 的状态。通常它是通过不向 class 的客户端代码提供 setter 方法来完成的。

static final关键字的组合用于使变量常量。声明为 final 的变量一旦被初始化就永远不能改变它的值。

因为在不可变的 class 中你永远不需要改变 property/field 状态,所以最好让它成为最终状态。

没有要求 使变量final。然而,当您确实明确打算永不更改变量时,将其设置为 final 通常是一种很好的做法,因为这不仅会针对拼写错误或其他错误强制执行不变量,而且还会声明它的意图对其他程序员或您自己不可变。

如果变量是 public,那么您将严格需要将其设为 final 以确保接口代码无法更改其值。

请注意,您 link 的问题没有直接关系,但是,因为它讨论 classesfinal,而不是变量。使 class final 意味着它不能被继承,而不是它是不可变的。但是,在制作不可变对象时,当然有必要注意该问题的内容及其答案;但这仍然是一个 单独的 问题。

通过标记 class 的所有字段 final,您明确表示您希望 class 不可变。

假设您有以下 class:

public class Immutable {
    private int value;

    public Immutable (int value) {
        this.value = value;
    }

    public int getValue () {
        return value;
    }
}

没有 setter 方法,因此可以很容易地假设此 class 是不可变的。现在是这样。但最终你的 class 会被其他程序员修改,这个程序员可能会在你的 class:

中添加一些方法
public class Immutable {
    private int value;

    public Immutable (int value) {
        this.value = value;
    }

    public int getValue () {
        return value;
    }

    public void doSomething () {
        value++;
    }
}

如果字段不是 final,很容易无意中添加修改对象状态的方法。通过将它们标记为 final,其他程序员在尝试修改该字段时将出现编译错误,并且将不得不问自己为什么这个字段是 final,他的修改是否破坏了 this 的契约class.

有人可能会争辩说应该使用 Javadoc 来记录说 class 是不可变的,但坦率地说,并不是每个人都阅读 Javadoc。我认为让代码自己说话更好。

之前的回答是错误的

要成为不可变对象,必须将所有属性声明为 final

Java 内存模型为 final 字段提供了某些保证,以防止它们在线程之间存在数据竞争时返回不正确的默认值。

参见 https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5-110 中的示例 17.5-2。