创建不可变类的条件?

时间:2013-08-16 05:37:21

标签: java immutability mutable

要创建一个不可变类,Effective Java有一个最后的条件。

要使类不可变,请遵循以下五条规则:

  

5-确保对任何可变组件的独占访问。如果您的类具有引用可变对象的任何字段,请确保该类的客户端无法获取对这些对象的引用。永远不要将这样的字段初始化为客户端提供的对象引用,也不要从访问者返回对象引用。在构造函数,访问器和readObject方法

中制作防御性副本(第24项)
public final class ImmutableClass {


    private MutableObject mutableObject;

    // If I should not provide getter for this object. Then what is the use of this variable after I have
    //initalised in the constructor
}

有人能解释一下这一点吗?

1 个答案:

答案 0 :(得分:3)

实际上相当简单。

基本上,它不是说...

1-提供对象可能包含的任何可变对象的任何引用。

因此,如果您的Class包含java.util.List作为其中一个字段,则任何使用您的Class的客户都无法直接获取List的引用}字段,通过public减速或某种吸气。

例如......

public class BadImmutableExample {
    public List<String> myStrings; // This can not be referenced by the client
    /*...*/
}

会很糟糕,因为任何机构都可以访问字段myStrings来修改...

如果您必须返回List中的值,您将需要返回List的副本(不是对它的引用)或返回值的数组,例如。

例如......

public class BadImmutableExample {
    private List<String> myStrings; // This can not be referenced by the client

    /*...*/

    public List<String> getMyStrings() {
        return myStrings;
    }
}

List myStrings公开给任何客户,这将允许他们修改它。

在这种情况下,您还可以使用Collections.unmodifiableList(myStrings)使列表无法修改,或者使用return new ArrayList<String>(myStrings)或返回String数组...

2-永远不要将这样的字段初始化为客户提供的对象......

基本上这意味着如果您的Class要求客户端使用某种值或值来播种它,则不应该直接维护它们,而是再次为您自己的引用制作副本。

例如......

public class BadImmutableExample {
    private List<String> myStrings; // This can not be referenced by the client

    public ImmutableExample(List<String> clientStrings) {
        myStrings = clientStrings;
    }
}

会破坏此规则,因为对clientStrings的任何更改都会立即反映在您的课程中。

相反,你可以做点像......

public class BetterImmutableExample {
    private List<String> myStrings; // This can not be referenced by the client

    public ImmutableExample(List<String> clientStrings) {
        myStrings = new ArrayList<String>(clientStrings);
    }
}

相反,它将复制客户提供的列表,但不再反映对其所做的更改(客户提供的列表)