Java默认接口方法具体用例 [英] Java default interface methods concrete use cases
问题描述
Java 9 即将推出,更多特性将添加到 Java 接口中,例如私有方法.接口中的 default
方法是在 Java 8 中添加的,本质上是为了 支持在集合中使用 lambdas,而不会破坏与该语言以前版本的复古兼容性.
Java 9 is near to come and more features will be added to Java interfaces, like private methods. default
methods in interfaces were added in Java 8, essentially to support the use of lambdas inside collections without breaking retro-compatibility with previous versions of the language.
在 Scala 中,trait
中的方法非常有用.但是,Scala 处理 trait
的方法与使用 default
方法的 Java 不同.考虑多重继承解析或使用 trait
s 作为 mixins.
In Scala, methods inside trait
s are quite useful. However, Scala has a different approach treating trait
s than Java with default
methods. Think to multiple inheritance resolution or the use of trait
s as mixins.
除了上述使用之外,在哪些实际场景中使用 default
方法是值得的?这几年是不是出现了一些使用它们的模式?使用这种方法可以解决哪些问题?
Apart the above use, which are the real scenarios in which using a default
methods is worth? During this years is it arisen some pattern that uses them? Which problems can I solve using this kind of methods?
推荐答案
Brian Goetz 和我在我们的 JavaOne 2015 演讲 API Design with Java 8 Lambda and Streams 中介绍了其中的一些内容.,最后有一些关于默认方法的材料.
Brian Goetz and I covered some of this at our JavaOne 2015 talk, API Design with Java 8 Lambda and Streams. Despite the title, there is some material at the end about default methods.
幻灯片:https://stuartmarks.files.wordpress.com/2015/10/con6851-api-design-v2.pdf
视频:https://youtu.be/o10ETyiNIsM?t=24m
我将在这里总结我们所说的关于默认方法的内容.
I'll summarize here what we said about default methods.
界面演变
默认方法的主要用例是接口演变.这主要是在不破坏向后兼容性的情况下向接口添加方法的能力.正如问题中所指出的,这最突出地用于添加允许将集合转换为流的方法以及将基于 lambda 的 API 添加到集合.
The primary use case of default methods is interface evolution. Mainly, this is the ability to add methods to interfaces without breaking backward compatibility. As noted in the question, this was most prominently employed to add methods allowing conversion of Collections to Streams and to add lambda-based APIs to Collections.
不过,还有其他几个用例.
There are several other use cases, though.
可选方法
有时接口方法在逻辑上是可选的".例如,考虑不可变集合上的 mutator 方法.当然,实现是需要的,但通常在这种情况下它会做的是抛出异常.这可以通过默认方法轻松完成.如果不想提供异常抛出方法,实现可以继承它,或者如果他们想提供一个实现,他们可以覆盖它.示例:Iterator.remove
.
Sometimes interface methods are logically "optional". Consider mutator methods on immutable collections, for example. Of course, an implementation is required, but usually what it will do in such cases is to throw an exception. This can easily be done in a default method. Implementations can inherit the exception-throwing method if they don't want to provide it, or they can override it if they want to provide an implementation. Example: Iterator.remove
.
便捷方法
有时为了方便调用者而提供了一个方法,并且有一个明显的和最佳的实现.此实现可以由默认方法提供.实现覆盖默认值是合法的,但通常没有理由,因此实现通常会继承它.示例:Comparator.reversed
, <代码>Spliterator.getExactSizeIfKnown, Spliterator.hasCharacteristics
.请注意,Spliterator
是在 Java 8 中引入的,包括默认方法,所以这显然不是接口演变的情况.
Sometimes a method is provided for the convenience of callers, and there is an obvious and optimal implementation. This implementation can be provided by a default method. It's legal for an implementation to override the default, but there's generally no reason, so implementations will usually inherit it. Examples: Comparator.reversed
, Spliterator.getExactSizeIfKnown
, Spliterator.hasCharacteristics
. Note that Spliterator
was introduced in Java 8, including the default methods, so this clearly wasn't a case of interface evolution.
简单的实现,旨在被覆盖
默认方法可以提供适用于所有实现的简单、通用的实现,但这可能不是最佳的.这有助于在初始启动期间实现,因为它们可以继承默认值并确保正确操作.但是,从长远来看,实现可能希望覆盖默认值并提供改进的自定义实现.
A default method can provide a simple, general implementation that works for all implementations, but that is probably suboptimal. This assists implementations during initial bring-up, because they can inherit the default and be assured of correct operation. However, in the long term, implementations will probably want to override the default and provide an improved, customized implementation.
示例:List.sort
.默认实现将列表元素复制到临时数组,对数组进行排序,然后将元素复制回列表.这是一个正确的实现,有时无法改进(例如对于 LinkedList
).但是,ArrayList
覆盖 sort
并就地对其内部数组进行排序.这避免了复制开销.
Example: List.sort
. The default implementation copies the list elements to a temporary array, sorts the array, and copies the elements back to the list. This is a correct implementation, and sometimes it can't be improved upon (e.g. for LinkedList
). However, ArrayList
overrides sort
and sorts its internal array in-place. This avoids the copying overhead.
现在,很明显 sort
在 Java 8 中被改造成 List
和 ArrayList
,所以进化并没有以这种方式发生.但是你可以很容易地想象出一个新的 List
实现.您最初可能会继承 sort
默认实现,同时正确实现基础知识.稍后,您可能会考虑实施定制的排序算法,以适应新实施的内部数据组织.
Now, obviously sort
was retrofitted onto List
and ArrayList
in Java 8, so the evolution didn't happen this way. But you could easily imagine bringing up a new List
implementation. You'd probably initially inherit the sort
default implementation while you're getting the basics implemented properly. Later on, you might consider implementing a customized sort algorithm that's tuned to your new implementation's internal data organization.
这篇关于Java默认接口方法具体用例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!