创建一个没有final字段的不可变对象?

Vin*_*C M 8 java oop final immutability

我们可以创建一个不可变对象,而不是所有字段都是final吗?

如果可能的话,几个例子会有所帮助.

Hei*_*bug 6

声明所有字段都是私有的,只定义getter:

public final class Private{
    private int a;
    private int b;

    public int getA(){return this.a;}
    public int getB(){return this.b;}
}
Run Code Online (Sandbox Code Playgroud)

引用@Jon Skeet的评论,最终的类修饰符对以下内容很有用:

虽然只是Private的实例是不可变的,但是子类的实例可能是可变的.所以接收类型为Private的引用的代码不能依赖它是不可变的而不检查它是否只是Private的实例.

因此,如果您想确定您所指的实例是不可变的,那么您还应该使用最终的类修饰符.


Jon*_*eet 6

是的,它是 - 只是确保你的州是私人的,你班上没有任何东西改变它:

public final class Foo
{
    private int x;

    public Foo(int x)
    {
        this.x = x;
    }

    public int getX()
    {
        return x;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个类中没有办法改变状态,因为它是最终的,你知道没有子类会添加可变状态.

然而:

  • 非最终字段的分配与最终字段的内存可见性规则并不完全相同,因此可以从不同的线程中观察对象"更改".有关最终字段保证的更多详细信息,请参见JLS的第17.5节.
  • 如果您不打算更改字段值,我个人会最终记录该决定并避免以后意外添加变异方法
  • 我不记得JVM是否阻止通过反射改变最终字段; 显然任何具有足够权限的调用者x可以在上面的代码中访问该字段,并使用反射对其进行变异.(根据评论,它可以用最终字段完成,但结果可能无法预测.)