使用Java中的getter方法返回私有集合

Jon*_*ny5 3 java

我有许多Java类在内部使用私有集或列表。我希望能够使用get ... List()方法返回这些集合/列表。

我正在考虑的替代方案:

  1. 返回对内部对象的引用
  2. 构造一个新的集合/列表并填充它(这似乎是不好的做法?)
  3. 使用 Collections.unmodifiableList(partitions);

以下哪项是解决此问题的最常见/最佳方法?

Mar*_*o13 5

这里有很多方面要考虑。正如其他人已经指出的那样,最终决定取决于您的意图,但是有关这三种选择的一些一般性声明:

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时,这些问题非常重要。一旦以一种或另一种方式实现了它,人们就会以一种或另一种方式来依赖行为。

因此,回到第一点:它始终取决于您要实现的目标。