这里的答案似乎有很多混乱。
Java 语言要求接口中的每个方法都由该接口的每个实现来实现。时期。这条规定没有例外。说“集合是一个例外”表明对这里真正发生的事情的理解非常模糊。
重要的是要认识到符合接口有两个级别:
Java 语言可以检查什么。这几乎可以归结为:是否存在some每个方法的实现?
-
实际履行合同。也就是说,实现是否按照接口中的文档所述执行操作?
编写良好的接口将包括准确解释实现预期内容的文档。您的编译器无法为您检查这一点。您需要阅读文档,并按照他们所说的去做。如果您不按照合同规定执行,那么您将获得该接口的实现compiler令人担忧,但这将是一个有缺陷/无效的实施。
在设计 Collections API 时,Joshua Bloch 决定不使用非常细粒度的接口来区分集合的不同变体(例如:可读、可写、随机访问等),而只使用非常粗略的接口集,主要是Collection
, List
, Set
and Map
,然后将某些操作记录为“可选”。这是为了避免细粒度接口导致的组合爆炸。来自Java 集合 API 设计常见问题解答 http://docs.oracle.com/javase/8/docs/technotes/guides/collections/designfaq.html#a1:
为了详细说明问题,假设您想添加
层次结构可修改性的概念。你需要四个新的
接口:ModABLECollection、ModABLESet、ModABLEList 和
可修改的地图。以前简单的层次结构现在变得混乱
异质性。此外,您还需要一个新的 Iterator 接口来使用
不可修改的集合,不包含删除操作。
现在可以取消 UnsupportedOperationException 了吗?很遗憾
不是。
考虑数组。他们实现了大部分列表操作,但没有
删除并添加。它们是“固定大小”列表。如果你想捕捉
在层次结构中,您必须添加两个新接口:
变量大小列表和变量大小映射。你不必添加
VariableSizeCollection 和 VariableSizeSet,因为它们是
与 ModificableCollection 和 ModulatedSet 相同,但您可能
为了保持一致性,无论如何选择添加它们。另外,你还需要一个新的
各种不支持add和remove的ListIterator
操作,与不可修改的列表一起进行。现在我们已经达到十个或
十二个接口,加上两个新的迭代器接口,而不是我们的
原四.我们完了吗?不。
考虑日志(例如错误日志、审核日志和日志)
可恢复的数据对象)。它们是自然的仅附加序列,
支持除删除和设置之外的所有列表操作
(代替)。它们需要一个新的核心接口和一个新的迭代器。
与不可修改的集合相比,不可变的集合又如何呢?
(即,客户无法更改的集合并且永远不会
因任何其他原因而改变)。很多人认为这是最
所有的重要区别,因为它允许多个线程
并发访问集合而不需要同步。
将此支持添加到类型层次结构中还需要四个
接口。
现在我们有大约二十个接口和五个迭代器,它是
几乎可以肯定,实践中仍然存在集合现象
不能完全融入任何界面。例如,
Map 返回的集合视图是自然的仅删除集合。
此外,有些集合会拒绝某些元素
它们的价值的基础,所以我们仍然没有取消运行时
例外情况。
总而言之,我们觉得这是一项完善的工程
通过提供非常小的一组妥协来回避整个问题
可以抛出运行时异常的核心接口。
当 Collections API 中的方法被记录为“可选操作”时,并不意味着您可以在实现中忽略方法实现,也不意味着您可以使用空方法体(一方面,许多他们需要返回结果)。相反,它意味着一个有效的实现选择(仍然符合合同的选择)是抛出一个UnsupportedOperationException http://docs.oracle.com/javase/7/docs/api/java/lang/UnsupportedOperationException.html.
请注意,因为UnsupportedOperationException
is a RuntimeException
就编译器而言,您可以从任何方法实现中抛出它。例如,您可以将其从以下实现中抛出Collection.size()
。然而,这样的实施将违反合同作为文件Collection.size()
并没有说这是允许的。
旁白:Java 的 Collections API 使用的方法有些争议(但是现在可能比首次引入时少)。在完美的世界中,接口将not有可选的操作,并且将使用细粒度的接口。问题是 Java 既不支持推断的结构类型也不支持交集类型,这就是为什么尝试以“正确的方式”做事最终在集合的情况下变得极其笨拙。