我的一个类有一个包含 Set 的字段。该字段仅在构造函数中填充,然后由其他类读取。最初我有这样的事情:
public class Foo {
public final Set<String> myItems;
public Foo(Collection<String> theirItems) {
this.myItems = new LinkedHashSet<String>(theirItems);
}
}
但这违背了面向对象的最佳实践,myItems 应该是私有的,并且只能通过 setter 和 getter 访问。于是我把它改成了:
public class Foo {
private final Set<String> myItems;
public Foo(Collection<String> theirItems) {
this.myItems = new LinkedHashSet<String>(theirItems);
}
public Set<String> getItems() {
return myItems;
}
}
现在 myItems 是私有的,但是调用 getItems() 的人仍然可以随意添加/删除项目,这与我之前的情况基本相同。(我实际上并不担心有人更改项目内容,这更像是一个理论问题)
于是我改变了 getItems() 以返回一个数组:
public String[] getItems() {
return myItems.toArray(new String[myItems.size()]);
}
现在我的物品真的很私密。不幸的是,我知道将读取项目的对象实际上想要使用 Set,因此它必须立即将数组转换回来。我还可以返回 myItems 的副本:
public Set<String> getItems() {
return new LinkedHashSet<String>(myItems);
}
这为调用者提供了他们想要的东西,但在每次访问时都会创建一个新的 Set。
在这种情况下你会怎么做——不惜一切代价保护隐私,接受原始结构的转换/复制,或者牺牲对集合内容的控制并依赖负责任的调用者?