简体   繁体   English

尽管有一个可变成员,我怎么能让这个类不可变?

[英]How can I make this class immutable despite having a mutable member?

I want to make the following class immutable, even though it has a mutable List member. 我想使下面的类不可变,即使它有一个可变的List成员。 How can I achieve this? 我怎样才能做到这一点?

class MyImmutableClass {
        private List<Integer> data;
        public MyImmutableClass(List<Integer> data) {
            this.data = data;
        }
        public List<Integer> getData() {
            return data;
        }
    }

Below is test class whose main() function that modifies object state. 下面是测试类,其main()函数修改了对象状态。

class TestMyImmutableClass{
    public static void main(String[] args) {
        List<Integer> data = new ArrayList<Integer>();
        data.add(2);
        data.add(5);
        MyImmutableClass obj = new MyImmutableClass(data);
        obj.getData().add(3);
        System.out.println("Data is; " + obj.getData());
    }
}

O/P : Data is; [2, 5, 3] O / P: Data is; [2, 5, 3] Data is; [2, 5, 3]

In you getData method, instead of returning a reference to your List like... getData方法中,而不是返回对List的引用,如...

public List<Integer> getData() {
    return data;
}

You could return an unmodifiable List instead 您可以返回不可修改的List

public List<Integer> getData() {
    return Collections.unmodifiableList(data);
}

See Collections.unmodifiableList for more details... 有关详细信息,请参阅Collections.unmodifiableList ...

Updated 更新

As pointed out by user949300, you should also make a copy of the original list. 正如user949300所指出的,您还应该复制原始列表。

public MyImmutableClass(List<Integer> data) {
    this.data = new ArrayList<Integer>(data);
}

This will prevent any one who has access to the original list from making modifications to it. 这将阻止任何有权访问原始列表的人对其进行修改。

In your constructor, go 在你的构造函数中,去吧

this.data = Collections.unmodifiableList(new ArrayList(data));

For completeness and clarity, declare the data field as final . 为了完整性和清晰度,将数据字段声明为final

If you're using Eclipse Collections , you can change the type of MyImmutableClass.data to ImmutableList . 如果您正在使用Eclipse Collections ,则可以将MyImmutableClass.data的类型MyImmutableClass.dataImmutableList

class MyImmutableClass {
    private ImmutableList<Integer> data;
    public MyImmutableClass(List<Integer> data) {
        this.data = Lists.immutable.withAll(data);
    }
    public ListIterable<Integer> getData() {
        return data;
    }
}

Eclipse Collection's ImmutableList and ListIterable types are contractually immutable, meaning they don't have add() and remove() methods. Eclipse Collection的ImmutableListListIterable类型是契约不可变的,这意味着它们没有add()remove()方法。 This way, it's clear from the return type of getData() that the returned list cannot be changed. 这样,从getData()的返回类型可以清楚地看出,返回的列表无法更改。

Both ImmutableList and MutableList extend ListIterable so you could change the implementation from an ImmutableList to an unmodifiable list without changing the API. 无论ImmutableListMutableList延长ListIterable ,所以你可以从一个实施改变ImmutableList一个不可修改的列表而不改变API。

class MyImmutableClass {
    private MutableList<Integer> data;
    public MyImmutableClass(List<Integer> data) {
        this.data = Lists.mutable.withAll(data);
    }
    public ListIterable<Integer> getData() {
        return data.asUnmodifiable();
    }
}

Note: I am a committer for Eclipse collections. 注意:我是Eclipse集合的提交者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM