我遇到过很多类似的代码:
class AClass{
private Iterable<String> list;
public AClass(Iterable<String> list){ this.list = list; }
...
}
在此代码中,Iterable的引用直接传递给AClass。最终结果相当于将列表引用直接暴露给外部。即使你最终制作了AClass.list,它仍然允许来自AClass之外的代码来修改列表的内容,这很糟糕。
为了解决这个问题,我们将在构造函数中执行防御性复制。
但是,这种代码很常见。除了性能考虑之外,人们编写这种代码的意图是什么?
答案 0 :(得分:1)
简单的回答,如果它是你自己的代码/小团队,通常只需更快,更容易,更少的内存和CPU密集型来做这样的事情。此外,有些人只是不知道更好!
答案 1 :(得分:1)
您可能需要查看copy constructor以获取熟悉的习语。
答案 2 :(得分:1)
我没有看到这种模式有什么问题。如果类表示对列表(或可迭代)进行操作的对象,那么将该列表提供给构造函数是很自然的。如果您的类无法处理对基础集合的更改,则需要对其进行修复或记录。制作该集合的副本是解决该问题的一种方法。
另一个选择是更改界面,以便只允许不可变的集合:
public AClass(ImmutableList<MyObject> objects) {
this.objects = objects;
...
当然,您需要某种ImmutableList类或接口。
根据课程的用途和用户,您还可以通过记录已知的&#34;弱点&#34;:
来避免复制。/**
* ...
* @param objects list of objects this AClass-object operates on.
* The list should not be modified during the lifetime
* of this object
*/
public AClass(List<MyObject> objects) ...
答案 3 :(得分:0)
制作副本总是很好的做法,不仅因为其他人可以修改您的值,而且出于安全原因。
答案 4 :(得分:0)
如果代码在内部使用,如其他答案所指出的那样,那应该不是问题。但是,如果您作为API公开,那么有两种选择:
首先是创建一个防御性副本,然后将其返回
第二种方法是创建一个UnmodifiableCollection
然后返回它,并记录试图改变集合中任何内容可能导致异常的事实。
但第一种选择更为可取。