4

I want to make the following class immutable, even though it has a mutable List member. 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.

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]

4

3 回答 3

7

在你getData的方法中,而不是返回对你List喜欢的引用......

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

你可以返回一个不可修改List

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

更多Collections.unmodifiableList详情请看...

更新

正如 user949300 所指出的,您还应该复制原始列表。

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

这将防止任何有权访问原始列表的人对其进行修改。

于 2013-09-05T03:43:43.690 回答
6

在你的构造函数中,去

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

为了完整和清晰起见,将数据字段声明为final.

于 2013-09-05T03:53:20.360 回答
2

如果您使用的是Eclipse Collections,则可以将类型更改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 的ImmutableListListIterable类型在合同上是不可变的,这意味着它们没有add()remove()方法。这样,从返回列表的返回类型就getData()可以看出,返回的列表是不能改变的。

两者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();
    }
}

注意:我是 Eclipse 集合的提交者。

于 2013-09-06T15:57:19.183 回答