我有许多在内部使用私有集或列表的Java类.我希望能够使用get … List()方法返回这些集/列表.
我正在考虑的替代方案:
>返回对内部对象的引用
>构建一个新的集/列表并填写它(这似乎是不好的做法?)
>使用Collections.unmodifiableList(partitions);
以下哪一项是解决此问题的最常见/最佳方式?
解决方法:
这里有许多方面需要考虑.正如其他人已经指出的那样,最终决定取决于你的意图,但有关这三个选项的一般性陈述:
1.返回对内部对象的引用
这可能会带来问题.当你这样做时,你几乎不可能保证一致的状态.调用者可能会获取列表,然后做一些讨厌的事情
List list = object.getList();
list.clear();
list.add(null);
...
也许不是出于恶意,而是偶然,因为他认为安全/允许这样做.
2.构建一个新的集/列表并填写它(这似乎是不好的做法?)
这不是一般的“坏习惯”.无论如何,它是API设计方面迄今为止最安全的解决方案.这里唯一需要注意的是,可能存在性能损失,具体取决于几个因素.例如.列表中包含多少元素,以及如何使用返回的列表.像这样的一些(可疑的?)模式
for (int i=0; i
{
Element element = object.getList().get(i);
...
}
可能会变得非常昂贵(尽管有人可能会争辩说,在这种特殊情况下,是否是这样实现它的用户的错,一般问题仍然有效)
3.使用Collections.unmodifiableList(partitions);
这是我个人经常使用的.它在API设计意义上是安全的,与复制列表相比,其开销只有微不足道.但是,调用者在获得对它的引用之后知道该列表是否可能发生变化是很重要的.
这导致…
最重要的建议:
记录方法正在做什么!不要写这样的评论
/**
* Returns the list of elements.
*
* @return The list of elements.
*/
public List getList() { ... }
而是指定您可以确定列表的内容.例如
/**
* Returns a copy of the list of elements...
*/
要么
/**
* Returns an unmodifiable view on the list of elements...
*/
就个人而言,我总是在这种文档的两个选项之间徘徊:
>明确该方法正在做什么以及如何使用它
>不要暴露或过度指定实施细节
例如,我经常写这样的文档:
/**
* Returns an unmodifiable view on the list of elements.
* Changes in this object will be visible in the returned list.
*/
第二句是关于行为的明确而有约束力的陈述.调用者知道这一点非常重要.对于并发应用程序(并且大多数应用程序以一种方式或另一种方式并发),这意味着调用者必须假定列表在获得引用后可能会同时更改,这可能会导致在发生更改时发生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...
*/
当您打算创建公共API时,这些问题主要是不重要的.一旦你以某种方式实现它,人们就会以一种或另一种方式依赖这种行为.
所以回到第一点:它总是取决于你想要达到的目标.
标签:java
来源: https://codeday.me/bug/20190722/1506855.html