为什么Collections类包含独立(静态)方法,而不是将它们添加到List接口?

对于将List作为第一个参数的集合中的所有方法,为什么这些方法不仅仅是List接口的一部分?

我的直觉是:给定一个List对象,该对象本身应“知道”如何对自身的操作执行,如rotate(),shuffle()或reverse()。 但相反,作为一名Java程序员,我必须检查List接口中的方法,以及Collections类中“在那里”的静态方法,以确保我使用规范解决方案。

为什么有些方法作为静态独立方法放在Collections类中,而不是添加到List接口(并且可能因此由某些现有或可能的基类实现)?

我正在努力更好地理解Java集合框架背后的设计决策。

这里有一些令人信服的OO设计原则,我忽略了吗? 或者仅仅出于某种实际的性能原因,这种区别是否已经完成

关键是,给定合适的基本操作(删除,设置等),可以实现一堆更高级别的操作(排序,随机,二进制搜索) 而不是由每个列表实现实现。

实际上,java.util.Collections就像.NET的Enumerable类 – 充满了可以在任何集合上工作的通用方法,因此它们可以共享单个实现并避免重复。

List接口的方法背后的理性

  1. List接口是Java运行时的一个非常核心的部分,在推出自己的List实现时完全实现所有成员已经有点繁重了。 因此,添加与列表定义无直接关系的额外方法有点无关紧要。 如果在List实现上需要这些方法,为什么不对接口进行子类化然后需要它们呢?
  2. 如果你要在1.3版中说到并通过添加新的实用程序方法向List接口添加function,那么你将破坏该接口的所有过去的实现者。
  3. 从域驱动设计的角度来看,集合中的实用程序方法不是列表的常规域的一部分。
  4. 关于OO设计原则,我认为在应用程序OO设计和语言运行时OO设计之间进行区分是很重要的。

Java的作者可能会做很多不同的事情,因为他们对API的多年使用有后见之明和前瞻性。 这就是说C#IList界面与Java非常相似,C#的作者确实有这个观点。

这肯定是某种程度上的判断。 我认为需要考虑的主要权衡是:当您向接口添加方法时,该接口的每个实现者都必须编写代码来实现它。

如果该方法的语义使得接口的不同实现最好以非常不同的方式实现这些语义,那么最好将它放在接口中。 (当然,如果语义根本无法根据接口中的其他方法定义,那么它必须是接口中自己的方法。)

另一方面,如果语义是可以根据接口中的其他方法定义的,并且接口的实现者只是倾向于反复编写相同的代码,那么最好制作实用程序方法将接口的实例作为参数。

它们是实用方法,而不是核心列表function。 如果添加了可以对List执行的所有操作,List接口就会变得臃肿。 集合中的操作不需要知道List的内部,它们在公共接口上运行,因此可以愉快地生活在外部类中。

这里有两种解释:

  1. 历史:集合类是在List接口之后创建的。 设计人员选择保留现有接口的向后兼容性。 否则许多开发人员将不得不改变他们的代码。

  2. 逻辑:您正在讨论的方法不需要有关List实现的内部知识,可以在实现它的任何集合上实现。