确保不可变列表中可变对象的不可变性

时间:2019-12-23 09:53:10

标签: java immutability

我需要实现不可变列表接口并修改其方法以确保列表的不可变性。

我认为我已经做到了,但是无法确保在此列表中找到的可变对象具有这种不变性。

考虑以下界面:

public interface ImmutableListInterface<T>{

        T get(int index);

}

及其实现:

public final class ImmutableList<T> implements ImmutableListInterface<T>{

    private final List<T> immutableList; 

    public ImmutableList(List<T> list) {
        immutableList = list;
    }

    @Override
    public T get(int index) {

        T item;
        List<T> temp = new ArrayList<>(immutableList);

        try {
            //Try retrieving item
            item = temp.get(index);

        }catch(Exception e) {
            System.out.println("Error message: " + e.getMessage());
            return null; 
        }

        return item;
    }
}

现在,如果要初始化类型为MutableObject的ImmutableList,这不会阻止我修改MutableObject的属性。如:

 class MutableObject{
    public int a;
}
        LinkedList<MutableObject> list = new LinkedList<MutableObject>();

        MutableObject object = new MutableObject();
        object.a = 0;

        list.add(object);

        ImmutableList<MutableObject> immutable_list = new ImmutableList<MutableObject>(list);

        System.out.println("Before:" +  immutable_list.get(0).a); //prints 0, as expected

        immutable_list.get(0).a = 1;
        System.out.println("After:" + immutable_list.get(0).a);//prints 1 - expecting 0

我尝试将方法设置为final,但无济于事。

似乎我可能忽略了我的实现中的某些内容。我如何真正确保列表的不变性,让对象本身保持可变性?

1 个答案:

答案 0 :(得分:0)

出现问题的原因是get()方法返回的对象是引用与您实际列表中的同一对象。因此,对其所做的更改将应用​​于您实际列表的对象。

另一方面,您不能确保列表内容的不变性,只能确保未修改其引用,而其值可能会更改。

如果您确实要在列表中保留对象并避免在get()之后修改列表的内容,建议您在方法中返回对象的深层副本。它将返回带有全新参考的相同对象,该参考不会链接到您的列表。

有几种方法可以找到,in this question