coo*_*ird 128
什么是不可变对象?
不可变对象是在实例化后不会改变状态的对象.
如何使对象不可变?
通常,可以通过定义一个没有暴露任何成员的类,并且没有任何setter来创建不可变对象.
以下类将创建一个不可变对象:
class ImmutableInt {
private final int value;
public ImmutableInt(int i) {
value = i;
}
public int getValue() {
return value;
}
}
Run Code Online (Sandbox Code Playgroud)
如在上面的例子中可以看出,的值ImmutableInt只能当对象被实例化设置,并且通过仅具有吸气剂(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;
}
}
Run Code Online (Sandbox Code Playgroud)
上述代码的问题在于,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");
Run Code Online (Sandbox Code Playgroud)
解决此问题的一种方法是从getter调用时返回数组或集合的副本:
public List<T> getList() {
// return a copy of the list so the internal state cannot be altered
return new ArrayList(list);
}
Run Code Online (Sandbox Code Playgroud)
不变性的优势是什么?
不可变性的优势在于并发性.在可变对象中难以保持正确性,因为多个线程可能试图改变同一对象的状态,导致一些线程看到同一对象的不同状态,这取决于对所述读取和写入的时间.宾语.
通过拥有一个不可变对象,可以确保查看该对象的所有线程都将看到相同的状态,因为不可变对象的状态不会改变.
Fab*_*eeg 18
除了已经给出的答案之外,我还建议阅读有效Java,第二版中的不变性,因为有些细节很容易被遗漏(例如防御性副本).另外,有效的Java第二版.是每个Java开发人员必读的.
你创建了一个类不可变的类:
public final class Immutable
{
private final String name;
public Immutable(String name)
{
this.name = name;
}
public String getName() { return this.name; }
// No setter;
}
Run Code Online (Sandbox Code Playgroud)
以下是使Java类不可变的要求:
final(因此无法创建子类)final(因此在创建对象后我们无法更改它的值)不可变类很有用,因为
它们是线程安全的.
- 他们还对你的设计表达了深刻的东西:"不能改变它.",当它适用时,它正是你所需要的.
不可变性主要有两种方式:
final实例属性来避免重新分配不变性的优点是您可以对这些对象做出的假设:
| 归档时间: |
|
| 查看次数: |
47932 次 |
| 最近记录: |