我有许多Java类在内部使用私有集或列表。我希望能够使用get ... List()方法返回这些集合/列表。
我正在考虑的替代方案:
Collections.unmodifiableList(partitions);以下哪项是解决此问题的最常见/最佳方法?
这里有很多方面要考虑。正如其他人已经指出的那样,最终决定取决于您的意图,但是有关这三种选择的一些一般性声明:
1.返回对内部对象的引用
这可能会带来问题。执行此操作时,几乎无法保证状态一致。呼叫者可能会获得列表,然后执行令人讨厌的事情
List<Element> list = object.getList();
list.clear();
list.add(null);
...
Run Code Online (Sandbox Code Playgroud)
也许不是恶意的意图却意外,因为他认为这是安全/允许这样做。
2.构造一个新的集合/列表并填充它(这似乎是不好的做法?)
通常,这不是“坏习惯”。无论如何,就API设计而言,它是迄今为止最安全的解决方案。唯一需要注意的是,可能会影响性能,具体取决于几个因素。例如,列表中包含多少个元素,以及如何使用返回的列表。像这样的一些(可疑的?)模式
for (int i=0; i<object.getList().size(); i++)
{
Element element = object.getList().get(i);
...
}
Run Code Online (Sandbox Code Playgroud)
可能变得昂贵得令人望而却步(尽管有人可能会争辩说在这种特殊情况下,是否是那样实施的是用户的过错,一般问题仍然有效)
3.使用Collections.unmodifiableList(partitions);
这是我个人经常使用的方式。从API设计的角度来看,它是安全的,并且与复制列表相比,其开销仅可忽略不计。但是,对于呼叫者来说,了解此列表在获得引用后是否可能会更改很重要。
这将导致...
记录该方法在做什么!不要写这样的评论
/**
* Returns the list of elements.
*
* @return The list of elements.
*/
public List<Element> getList() { ... }
Run Code Online (Sandbox Code Playgroud)
相反,请指定您可以确保列表的内容。例如
/**
* Returns a copy of the list of elements...
*/
Run Code Online (Sandbox Code Playgroud)
要么
/**
* Returns an unmodifiable view on the list of elements...
*/
Run Code Online (Sandbox Code Playgroud)
就个人而言,我总是为这样的文档在两个选择之间感到困惑:
因此,例如,我经常写这样的文档:
/**
* Returns an unmodifiable view on the list of elements.
* Changes in this object will be visible in the returned list.
*/
Run Code Online (Sandbox Code Playgroud)
第二句话是关于该行为的明确且具有约束力的陈述。呼叫者必须知道这一点,这一点很重要。对于并发应用程序(和大多数应用程序都以某种方式或其他并发),这意味着,调用者有假设后,他获得的参考,这可能会导致一个列表可以同时改变ConcurrentModificationException时的变化情况,而他是遍历列表。
但是,这样的详细规范限制了以后更改实现的可能性。如果您以后决定返回内部列表的副本,则行为将以不兼容的方式更改。
因此有时我也明确指定未指定行为:
/**
* Returns an unmodifiable list of elements. It is unspecified whether
* changes in this object will be visible in the returned list. If you
* want to be informed about changes, you may attach a listener to this
* object using this-and-that method...
*/
Run Code Online (Sandbox Code Playgroud)
当您打算创建公共API时,这些问题非常重要。一旦以一种或另一种方式实现了它,人们就会以一种或另一种方式来依赖行为。
因此,回到第一点:它始终取决于您要实现的目标。