问题描述
根据我的理解,如果您在 java 中实现一个接口,则该接口中指定的方法必须由实现所述接口的子类使用.
From my understanding if you implement an interface in java, the methods specified in that interface have to be used by the sub classes implementing the said interface.
我注意到在某些接口(例如 Collection 接口)中,有些方法被注释为可选,但这究竟是什么意思?它让我有点担心,因为我认为接口中指定的所有方法都是必需的?
I've noticed that in some interfaces such as the Collection interface there are methods which are commented as optional, but what exactly does this mean? Its thrown me a bit as I thought all methods specified in the interface would be required?
推荐答案
这里的答案似乎非常混乱.
There seems to be an awful lot of confusion in the answers here.
Java 语言要求接口中的每个方法都由该接口的每个实现来实现.时期.这条规则没有例外.说集合是一个例外"表明对这里真正发生的事情的理解非常模糊.
The Java language requires that every method in an interface is implemented by every implementation of that interface. Period. There are no exceptions to this rule. To say "Collections are an exception" suggests a very fuzzy understanding of what's really going on here.
重要的是要意识到符合接口有两种级别:
It's important to realize that there are sort of two levels of conforming to an interface:
Java 语言可以检查什么.这几乎可以归结为:每种方法都有一些实现吗?
实际履行合同.也就是说,该实现是否按照界面中的文档所说的那样做?
Actually fulfilling the contract. That is, does the implementation do what the documentation in the interface says it should?
编写良好的接口将包括文档,准确解释实现的预期内容.您的编译器无法为您检查这一点.你需要阅读文档,并按照他们说的去做.如果您不按照合同的规定去做,那么就编译器而言,您将获得接口的实现,但这将是一个有缺陷/无效的实现.
Well written interfaces will include documentation explaining exactly what is expected from implementations. Your compiler can't check this for you. You need to read the docs, and do what they say. If you don't do what the contract says then you'll have an implementation of the interface as far as the compiler is concerned, but it will be a defective/invalid implementation.
在设计集合 API 时,Joshua Bloch 决定,与其使用非常细粒度的接口来区分集合的不同变体(例如:可读、可写、随机访问等),他只会拥有非常粗略的集合接口,主要是Collection
、List
、Set
和 Map
,然后将某些操作记录为可选".这是为了避免细粒度界面导致的组合爆炸.来自 Java 集合 API 设计常见问题:
When designing the Collections API Joshua Bloch decided that instead of having very fine-grained interfaces to distinguish between different variants of collections (eg: readable, writable, random-access, etc.) he'd only have very coarse set of interfaces, primarilyCollection
, List
, Set
and Map
, and then document certain operations as "optional". This was to avoid the combinatorial explosion that would result from fine-grained interfaces. From the Java Collections API Design FAQ:
为了详细说明问题,假设您要添加层次结构的可修改性的概念.你需要四个新的接口:ModifiableCollection、ModifiableSet、ModifiableList 和可修改地图.以前简单的层次结构现在变得杂乱无章异质性.此外,您需要一个新的 Iterator 接口用于不可修改的集合,不包含删除操作.现在你能去掉 UnsupportedOperationException 吗?很遗憾不是.
考虑数组.它们实现了大部分 List 操作,但不实现删除并添加.它们是固定大小"的列表.如果你想捕捉层次结构中的这个概念,您必须添加两个新接口:VariableSizeList 和 VariableSizeMap.你不必添加VariableSizeCollection 和 VariableSizeSet,因为它们是与 ModifiableCollection 和 ModifiableSet 相同,但您可能为了一致性起见,无论如何选择添加它们.另外,你需要一个新的各种不支持添加和删除的 ListIterator操作,与不可修改的列表一起使用.现在我们最多十个或十二个接口,加上两个新的迭代器接口,而不是我们的原四.我们完了吗?号
Consider arrays. They implement most of the List operations, but not remove and add. They are "fixed-size" Lists. If you want to capture this notion in the hierarchy, you have to add two new interfaces: VariableSizeList and VariableSizeMap. You don't have to add VariableSizeCollection and VariableSizeSet, because they'd be identical to ModifiableCollection and ModifiableSet, but you might choose to add them anyway for consistency's sake. Also, you need a new variety of ListIterator that doesn't support the add and remove operations, to go along with unmodifiable List. Now we're up to ten or twelve interfaces, plus two new Iterator interfaces, instead of our original four. Are we done? No.
考虑日志(例如错误日志、审计日志和日志)可恢复的数据对象).它们是自然的仅追加序列,支持除 remove 和 set 之外的所有 List 操作(代替).它们需要一个新的核心接口和一个新的迭代器.
Consider logs (such as error logs, audit logs and journals for recoverable data objects). They are natural append-only sequences, that support all of the List operations except for remove and set (replace). They require a new core interface, and a new iterator.
与不可修改的集合相反,不可变集合呢?(即,客户端无法更改的集合,并且永远不会因任何其他原因更改).许多人认为这是最所有的重要区别,因为它允许多个线程无需同步即可同时访问集合.将此支持添加到类型层次结构还需要四个接口.
And what about immutable Collections, as opposed to unmodifiable ones? (i.e., Collections that cannot be changed by the client AND will never change for any other reason). Many argue that this is the most important distinction of all, because it allows multiple threads to access a collection concurrently without the need for synchronization. Adding this support to the type hierarchy requires four more interfaces.
现在我们有多达二十个左右的接口和五个迭代器,它是几乎可以肯定,在实践中仍有收集不适合任何接口.例如,Map 返回的集合视图是自然只删除集合.此外,有些集合会拒绝某些元素基于它们的价值,所以我们还没有取消运行时例外.
Now we're up to twenty or so interfaces and five iterators, and it's almost certain that there are still collections arising in practice that don't fit cleanly into any of the interfaces. For example, the collection-views returned by Map are natural delete-only collections. Also, there are collections that will reject certain elements on the basis of their value, so we still haven't done away with runtime exceptions.
当一切都说完了,我们觉得这是一个声音工程通过提供一个非常小的集合来回避整个问题可以抛出运行时异常的核心接口.
When all was said and done, we felt that it was a sound engineering compromise to sidestep the whole issue by providing a very small set of core interfaces that can throw a runtime exception.
当 Collections API 中的方法被记录为可选操作"时,这并不意味着您可以将方法实现留在实现中,也不意味着您可以使用空方法体(一方面,很多都需要返回结果).相反,它意味着一个有效的实现选择(一个仍然符合合同的选择)是抛出一个 UnsupportedOperationException
.
When methods in the Collections API are documented as being "optional operations", it does not mean that you can just leave the method implementation out in the implementation, nor does it mean you can use an empty method body (for one thing, many of them need to return a result). Rather, it means that a valid implementation choice (one that still conforms to the contract) is to throw an UnsupportedOperationException
.
请注意,因为 UnsupportedOperationException
是一个 RuntimeException
,您可以从任何方法实现中抛出它,就编译器而言.例如,您可以从 Collection.size()
的实现中抛出它.但是,这样的实现会违反合同,因为 Collection.size()
的文档没有说这是允许的.
Note that because UnsupportedOperationException
is a RuntimeException
you can throw it from any method implementation, as far as the compiler is concerned. For example, you could throw it from an implementation of Collection.size()
. However, such an implementation would violate the contract as the documentation for Collection.size()
does not say that this is permitted.
旁白:Java 的 Collections API 使用的方法有些争议(不过现在可能比首次引入时少).在完美的世界中,接口将没有可选操作,而是使用细粒度的接口.问题在于 Java 既不支持推断结构类型,也不支持交叉类型,这就是为什么尝试以正确的方式"做事在集合的情况下最终变得非常笨拙.
Aside: The approach used by Java's Collections API is somewhat controversial (probably less now than when it was first introduced, however). In a perfect world, interfaces would not have optional operations, and fine grained interfaces would instead be used. The problem is that Java supports neither inferred structural types or intersection types, which is why attempting to do things the "right way" ends up becoming extremely unwieldy in the case of collections.
这篇关于Java 接口中的可选方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!