我们可以创建一个不可变对象,而不是所有字段都是最终的吗?
如果可能,有几个例子会有所帮助。
答案 0 :(得分:6)
声明所有字段为私有且仅定义getter:
public final class Private{
private int a;
private int b;
public int getA(){return this.a;}
public int getB(){return this.b;}
}
引用@Jon Skeet的评论,最终的类修饰符对以下内容很有用:
虽然Just的实例是不可变的,但是一个实例 子类可能是可变的。所以代码接收类型的引用 私人不能依赖它是不可变的而不检查它是不是 只是私人的例子。
因此,如果您想确定您引用的实例是不可变的,那么您还应该使用final final修饰符。
答案 1 :(得分:6)
是的,它是 - 只是确保你的州是私人的,你班上没有任何东西改变它:
public final class Foo
{
private int x;
public Foo(int x)
{
this.x = x;
}
public int getX()
{
return x;
}
}
没有办法在这个类中改变状态,因为它是最终的,你知道没有子类会添加可变状态。
然而:
x
字段在上面的代码中可访问,并使用反射进行变异。 (根据评论,可以完成最终字段,但结果可能无法预测。)答案 2 :(得分:3)
术语“不可变”,当用于描述Java对象时,应该意味着线程安全的不变性。如果一个对象是不可变的,通常应该理解任何线程必须遵守相同的状态。
单线程不变性并不是很有趣。如果这是真正提到的,它应该完全符合“单线程”;一个更好的术语是“不可修改的”。
问题是官方提到对“不可变”一词的严格使用。我不能;它基于Java大人物如何使用这个术语。每当他们说“不可变对象”时,他们总是在谈论线程安全的不可变对象。
实现不可变对象的惯用方法是使用final
个字段; final
语义被专门升级为支持不可变对象。这是一个非常有力的保证;事实上,final
字段是唯一的方式; volatile
个字段甚至synchronized
块无法阻止在构造函数完成之前发布对象引用。
答案 3 :(得分:1)
是的,如果您创建的对象只包含私有成员且没有提供setter,那么它将是不可变的。
答案 4 :(得分:1)
我相信答案是肯定的。
考虑以下对象:
public class point{
private int x;
private int y;
public point(int x, int y)
{
this.x =x;
this.y =y;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
}
此对象是不可变的。
答案 5 :(得分:1)
如果类不提供可从外部访问的任何修改对象状态的方法,则该类是不可变的。所以是的,你可以创建一个不可变的类而不使字段最终。例如:
public final class Example {
private int value;
public Example(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
但是,没有必要在实际程序中执行此操作,如果您的类应该是不可变的,建议始终将字段设为final。
答案 6 :(得分:0)
是。将字段设为私有。不要在构造函数以外的任何方法中更改它们。当然,既然如此,你为什么不把它们标记为最终的???