Java:没有来自外部类的ArrayList修改

时间:2014-12-24 10:46:47

标签: java class arraylist runtimemodification

我在我的一个Java项目类中使用了一个ArrayList。该类会跟踪列表是否已更改,并提供了一些公共方法来添加和删除列表中自动将变量设置为“已更改”的元素。

到目前为止,该列表是公开的,因为我希望我的列表可以从任何地方公开读取。但我只希望拥有该列表的类能够修改它。所以没有来自外部类的修改。那可能吗?如果是这样,怎么样?

通常对于访问控制,您可能使用getter和setter方法。但即使使用getter方法并将列表设置为private,另一个类仍然可以执行getList().remove(element),从而从外部修改列表,而不会注意到列表已更改。

5 个答案:

答案 0 :(得分:2)

将您的ArrayList字段设为私有,但让您的getter返回Collections.unmodifiableList(list),它提供了一个不可修改的视图。

这将允许外部代码将其视为普通List,用于每个循环等,但将禁用修改操作。此外,unmodifiableList以固定时间返回视图。

这实际上是它的设计用例。的Javadoc:

  

此方法允许模块为用户提供对内部列表的“只读”访问权限。对返回列表的查询操作“读取”到指定列表,并尝试修改返回的列表,无论是直接还是通过其迭代器,都会导致UnsupportedOperationException。

答案 1 :(得分:1)

您可以将ArrayList成员设为私有,而不是返回ArrayList的getter,而是使用接受索引i的getter并返回i& #39; ArrayList的元素。

public class Test
{
    private List<String> list = new ArrayList<String>();

    public getString (int i)
    {
        // you might want to add some validation of i here
        return list.get(i);
    }

}

getString允许您的类用户访问列表中的任何元素,而无法对其进行修改。

如果您希望允许您的用户迭代列表而不能修改它,您可以添加getSize()方法来返回列表的大小(这将允许用户迭代列表使用常规for循环),或者您的类可以实现Iterable(不支持删除操作)。

答案 2 :(得分:1)

将您的列表设为私有并添加getter方法:

public List getList(){
    return new ArrayList(yourPrivateList);
}

答案 3 :(得分:1)

你有几个选择:

  • 返回ArrayList的getter可以在返回对象之前进行克隆。这样,即使外部实体修改了对象,它们也最终会修改克隆 - 而不是原始对象。注意:克隆操作可能成本很高。我建议使用以下选项。
  • 使用Collections.unmodifiableList(..)Check the documentation here.
  • 或者其他答案建议:推出自己的访问和迭代方法。

答案 4 :(得分:0)

我认为您最好的选择是保持List 隐私并添加一个getter方法,该方法返回List的副本,但不会返回List的副本本身。例如:

public class EncapsulationTest {

    private List<Object> privateList = new ArrayList<Object>();

    // Your constructors and methods to track list
    // modification here ...

    public List<Object> getList() {
        // Maybe you need a null check here
        return new ArrayList<Object>(privateList);
    }

    public void addElement(Object newElement) {
        this.privateList.add(newElement);
        // Set your 'changed' variable to true
    }

    public void removeElement(Object element) {
        this.privateList.remove(element);
        // Set your 'changed' variable to true
    }
}

如果您这样做,您仍然可以阅读List完全副本,但无法修改List本身。实际上,您可以修改返回的List,但由于它是一个不同的对象,因此更改不会影响对象的List

我希望它有所帮助。