在对象中初始化一个集合?

如果对象具有属于集合的属性,那么对象是应该创建集合对象还是让使用者检查null? 我知道消费者不应该假设,只是想知道大多数人是否创建了集合对象,如果它从未被添加到。

您也可以使用“Lazy initailizer”模式,其中集合未初始化,直到(并且除非)有人访问它的属性getter …这避免了在父对象被实例化为某些其他情况的情况下创建它的开销。不需要收集的目的……

public class Division { private int divId; public int DivisionId { get; set; } private Collection emps; public Collection Employees { get {return emps?? (emps = new Collection(DivisionId));}} } 

编辑:这个实现模式通常不是线程安全的……在第一个线程完成修改之前,emps可以被两个不同的线程读取为null。 在这种情况下,它可能无关紧要,因为DivisionId是不可变的,虽然两个线程都会得到不同的集合,但它们都是有效的。 因此,当第二个线程掠过时,emps将是一个有效的集合。 ‘可能’是因为第一个线程可能在第二个线程重置之前开始使用emps。 这不是线程安全的。 Jon SKeet的另一个稍微复杂的实现是线程安全的(参见本文关于SIngletons的例子/讨论如何解决这个问题。

这取决于您与API和用户之间的合同。

就个人而言,我喜欢让Object管理其集合的合同,即在创建时实例化它们,并确保它们不能通过setter设置为null – 可能通过提供管理集合的方法而不是设置集合本身。

即,addFoo(Foo toAdd)而不是setFooSet(Set set),依此类推。

但这取决于你。

我通常会创建集合,然后提供从内部集合添加/删除项目的方法,而不是让类的使用者担心检查null。 这也使您能够更好地控制集合中发生的事情。 最终它取决于它的用途,但最有可能的是,如果你的类有一个集合,那么这个集合的消费者不仅可以拥有这些对象的集合。 否则,为什么他们会使用你的课程?

虽然我在这里所说的并不是通用的,但我认为集合最适合作为私有属性,应该通过对象本身的公共方法来访问。 因此,对象负责根据需要创建和销毁它们。 这样,就无法从外部代码将其设置为null。

我更喜欢在实例化时创建集合,在包含对象中提供添加/删除方法,如果需要,还提供addAll / removeAll方法来添加和删除整个外部集合。 我从不允许调用者访问或设置集合对象 – 但是,我可以提供一个返回集合的副本(可能是不可变的)的getter。

我还有写入时复制实现,它提供了一个不可变的包装视图,因为任何突变都会创建一个新的底层集合。

我创建了一个空集合。 当然,它有一点点内存成本,但不足以引起人们的关注。

IMO,这是IEnumerable很好的地方。

就个人而言,我喜欢将我的“集合”属性初始化为空列表。

如果集合是对象的固有部分,那么对象通常应该创建它(并且不允许用户将其设置为不同的集合实例)。

我已经尝试了两种方式,当我发现我已经实现了它时,我通常很高兴。 或者,您可以隐藏一组可以为您处理检查的方法背后的消费者实现。

作为一般规则,我认为对象应该创建集合并提供操作它的方法; 添加/获取/删除。 遵循此规则时,不应提供直接设置集合的方法。 如果你想要一个像setSomeCollection(Collection someCollection)这样的方法,为了方便起见,这个方法的实现不应该在对象中设置引用,而是将方法参数集合中的值复制到对象中的集合中;

 public void setSomeCollection(Collection someCollection) { this.someCollection.clear(); this.someCollection.addAll(someCollection); } 

您应该这样做,因此API的客户端无法访问您的类所维护的集合。 如果他们这样做,他们可以在不使用你的类的对象的情况下操纵它,并违反你的class级保证的约束。

如果提供吸气剂也是如此; 您应该返回内部集合的副本或其只读版本。 Apache commons-collections和google-collections提供了在集合中创建不可变包装器的方法,以及java.util包中随Java附带的方法。 java.util.Collections.unmodifiable *。