3 回答

TA贡献1859条经验 获得超6个赞
什么是不可变的对象?
不变对象是在实例化后不会改变状态的对象。
如何使对象不变?
通常,可以通过定义一个不暴露任何成员且没有任何设置方法的类来创建不可变对象。
以下类将创建一个不可变的对象:
class ImmutableInt {
private final int value;
public ImmutableInt(int i) {
value = i;
}
public int getValue() {
return value;
}
}
从上面的示例可以看出,ImmutableInt只能在实例化对象时设置the的值,并且通过仅使用getter(getValue),在实例化后不能更改对象的状态。
但是,必须注意,该对象引用的所有对象也必须是不可变的,否则可能会更改该对象的状态。
例如,允许对数组的引用或ArrayList通过getter获取将允许通过更改数组或集合来更改内部状态:
class NotQuiteImmutableList<T> {
private final List<T> list;
public NotQuiteImmutableList(List<T> list) {
// creates a new ArrayList and keeps a reference to it.
this.list = new ArrayList(list);
}
public List<T> getList() {
return list;
}
}
上面的代码的问题在于,ArrayList可以通过获取getList和操纵它们,从而导致对象本身的状态被改变,因此,它不是不变的。
// notQuiteImmutableList contains "a", "b", "c"
List<String> notQuiteImmutableList= new NotQuiteImmutableList(Arrays.asList("a", "b", "c"));
// now the list contains "a", "b", "c", "d" -- this list is mutable.
notQuiteImmutableList.getList().add("d");
解决此问题的一种方法是从getter调用时返回数组或集合的副本:
public List<T> getList() {
// return a copy of the list so the internal state cannot be altered
return new ArrayList(list);
}
不变性的优点是什么?
不变性的优点在于并发。在可变对象中很难保持正确性,因为多个线程可能试图更改同一对象的状态,从而导致某些线程看到同一对象的不同状态,具体取决于读取和写入对象的时间宾语。
通过拥有一个不可变的对象,可以确保所有正在查看该对象的线程都将看到相同的状态,因为不可变的对象的状态不会改变。

TA贡献1780条经验 获得超1个赞
不变性主要可以通过两种方式实现:
使用final实例属性避免重新分配
使用一个类接口,该接口根本不允许任何能够修改类内部内容的操作(仅使用getter而不使用setter)
不变性的优点是可以对这些对象进行以下假设:
您将获得无副作用规则(在函数式编程语言上非常流行),并允许您更轻松地在并发环境中使用对象,因为您知道当对象被使用时,不能以原子或非原子的方式对其进行更改被许多线程使用
语言的实现可以以不同的方式对待这些对象,将它们放置在用于静态数据的内存区域中,从而可以更快,更安全地使用这些对象(这是在JVM中用于字符串的情况)
添加回答
举报