我们是否可以在不将所有字段设置为final的情况下创建不可变对象?
如果可能,举几个例子会很有帮助。
我们是否可以在不将所有字段设置为final的情况下创建不可变对象?
如果可能,举几个例子会很有帮助。
将所有字段声明为私有,并仅定义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的评论,final类修饰符对以下情况非常有用:
虽然仅具有Private修饰符的实例是不可变的,但子类的实例可能是可变的。因此,接收类型为Private的引用的代码不能依赖于它是不可变的,除非检查它是否是仅具有Private修饰符的实例。
因此,如果您希望确保所引用的实例是不可变的,则还应使用final类修饰符。
Private
的实例是不可变的,但子类的实例可能是可变的。因此,接收类型为 Private
的引用的代码不能依赖于它是不可变的,而必须检查它是否只是 Private
的实例。 - Jon Skeet是的,它可以 - 只需确保您的状态是私有的,并且类中的任何内容都不会改变它:
public final class Foo
{
private int x;
public Foo(int x)
{
this.x = x;
}
public int getX()
{
return x;
}
}
在这个类中,没有任何一种方式可以改变状态,并且因为它是final的,所以你知道没有子类会添加可变状态。
然而:
x
字段可访问,并使用反射进行更改。(根据评论,可以使用final字段进行更改,但结果可能是不可预测的。)final
字段;final
语义特别升级以支持不可变对象。这是一个非常强的保证;事实上,final
字段是唯一的方法;volatile
字段甚至synchronized
块都不能防止构造函数完成之前发布对象引用。我相信答案是肯定的。
考虑以下对象:
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;
}
}
此对象为不可变对象。
public final class Example {
private int value;
public Example(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
然而,在实际编程中并不需要这样做,如果你的类应该是不可变的,建议始终将字段设置为final。
是的,如果您创建了一个仅包含私有成员且没有提供设置器的对象,则它将是不可变的。
是的,把字段设置为私有的。除了构造函数之外,不要在任何其他方法中更改它们。当然,既然如此,为什么不将它们标记为final呢?
final
只能帮助编译器捕获一些错误。一个类可以具有final
字段而可变,也可以没有它们而不可变。然而,如果您有一个不可具有final
字段的不可变类,那么您必须问为什么会这样... ;) - Peter Lawreyfinal
字段呢? - David Snabel-Caunt