在 Java 中返回内部集合的最佳实践是什么?
我很好奇从可变类返回对象集合时什么被认为是更好的做法:
public class Someclass {
public List<String> strings;
public add(String in){ strings.add(in); }
public remove(String in) { strings.remove(in); }
//THIS
public List<String> getStrings(){
return Collections.unmodifiableList(strings);
}
//OR THIS
public List<String> getStrings(){
return new ArrayList(strings);
}
}
我总是认为将内部集合包装在不可修改的集合中是最好的方法,因为我没有看到产生创建开销的原因复制。然而,我突然想到,内部对列表所做的任何更改都会暴露给客户,这让我觉得很糟糕。
I'm curious what is considered a better practice when returning a collection of objects from a mutable class:
public class Someclass {
public List<String> strings;
public add(String in){ strings.add(in); }
public remove(String in) { strings.remove(in); }
//THIS
public List<String> getStrings(){
return Collections.unmodifiableList(strings);
}
//OR THIS
public List<String> getStrings(){
return new ArrayList(strings);
}
}
I always assumed wrapping the internal collection in an Unmodifiable was the best approach since I didn't see a reason to incur the overhead of creating a copy. However, it occurred to me that any changes made to the list internally would be exposed to the client which strikes me as bad.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为对此没有简单的“最佳实践”答案。这实际上取决于您愿意花费多少机器资源来防止违反类数据抽象边界。这取决于您实际上想要减轻哪些风险;例如,是简单(非并发)错误、并发错误还是信息泄漏。
选项有:
除了复制的直接成本之外,其他与性能相关的因素还有内存使用和垃圾生成以及对并发的影响。例如,如果多个线程正在更新集合和/或“获取”它,那么制作集合的副本通常需要锁定它......这可能会使操作成为并发瓶颈。
总之,您需要平衡成本/性能影响与不采取预防措施的潜在或实际风险和成本。
I don't think there is a simple "best practice" answer to this. It really depends on how much of the machine's resources you are willing to spend on preventing violation of the classes data abstraction boundaries. And it depends on what risks you are actually trying to mitigate; e.g. is it simple (non-concurrent) bugs, concurrency bugs, or information leaks.
The options are:
In addition to the direct costs of copying, other performance-related factors are memory usage and garbage generation and the impact on concurrency. For instance, if multiple threads are updating the collection and/or "getting" it, then making a copy of the collection typically involves locking it ... which could potentially make the operation a concurrency bottleneck.
In summary, you need to balance the cost / performance implications against the potential or actual risks and costs of not taking the precautions.
我喜欢后者,但使用
.clone()
方法。I like to do the latter, but using the
.clone()
method.如果您担心公开更改;并且您的对象实现了 Cloneable,那么您可以将对象列表的克隆深层副本返回给调用者。
If you are concerned about exposing changes; and your object implements Cloneable, then you can return a Cloned deep copy of your object list back to the invoker.
'new ArrayList(strings)' 比 'Collections.unmodifyingList(strings)' 更安全。
因为 Collections.unmodifyingList 只是转发源列表。
示例:
现在,您将看到 list1 已添加!列表2 没有。
'new ArrayList(strings)' is safer than 'Collections.unmodifiableList(strings)'.
Because Collections.unmodifiableList just forwards the source list.
Sample:
Now, you'll see list1 is added! list2 not.