是否可以在不破坏 Java 的情况下将默认方法添加到 Comparable?

Would it be possible to add default methods to Comparable without breaking Java?

我正在考虑提出一个功能请求来添加名为的默认方法:

default boolean greaterThan(T o) {
    return compareTo(o) > 0;
}

default boolean smallerThan(T o) {
    return compareTo(o) < 0;
}

default boolean atLeast(T o) {
    return compareTo(o) >= 0;
}

default boolean atMost(T o) {
    return compareTo(o) <= 0;
}

Comparable 接口,因为它会使代码更具可读性 - 在我看来。

但是,我想知道这是否会破坏代码。如果我们添加默认方法,是否有任何代码(如 Lambda 代码)会中断?

如果我没看错 ,我会假设 Lambda 至少会继续工作,只要它们不会尝试调用新方法,但我不确定。而且我不知道是否还有任何(明显的)其他问题。

请不要讨论可能的功能请求本身。

作为, Stuart Marks documented a case where adding the CharSequence.isEmpty() 默认方法Java 15 破坏了第三方库。

因此,考虑到使用现有应用程序最大程度地 backward-compatible 制作更新版本 Java 的历史优先级,更好的方法是定义一个新界面。新界面将介绍您的新方法。从理论上讲,经过很长一段时间后,旧界面最终可能会被标记为已弃用,以建议逐步淘汰旧界面以换取新界面。同时,现有代码不会受到干扰,新代码可以利用新思想。

这是在 Map interface. The sub-interface SortedMap arrived with Java 1.2 (a.k.a. Java 2). Years later, in Java 6, came the idea to extend that interface with additional methods. But revising SortedMap runs the risk of disturbing existing implementations within the bundled Java libraries as well as breaking third-party implementations. So they chose to instead define a new interface NavigableMap 中完成的。他们使较新的界面 NavigableMap 成为 SortedMap.

的子界面

NavigableMap 实际上只是 SortedMap 的“2.0”版本。据我所知,没有任何实现不希望支持更多方法而不是 SortedMap 中发现的较少方法的原因。所以,当然,只有一个这样的界面而不是两个会很好,但是 c'est la vie.

这是我制作的一张图 table,展示了与 Java 11 捆绑在一起的 Map 接口的各种实现。您可以看到接口 SortedMapNavigableMap 并排生活。

我全心全意支持您使用这些特定方法(顺便说一句,命名也不错)有效扩展 Comparable 的想法。但我相信你的提议只会作为 Comparable.

的新子接口运行

不幸的是,@BasilBourque 的回答具有误导性,尽管它引用了有用的实体。

不可能通过子界面引入此功能。 SortedMap/NavigableMap 适用:default 机制在引入 NavigableMap 时还不存在!

在这一点上,可能值得将 NavigableMap 中的部分或全部方法作为 SortedMap 中的 default 方法进行介绍,并实现在 sortedmaps 上工作并且将自动结束被任何已经实现 NavigableMap 的 Map impls 覆盖(因为它们已经覆盖了他们 impl 中的所有那些)。

然而,这意味着 'Hey, look at NavigableMap which is analogous to SortedMap just like what you want to do to Comparable' 是 一个误导性的论点 :您的建议涉及添加默认方法。那只是当时 table 上没有的。

最后你想要的是'almost, but not entirely, backwards compatible'。 Oracle/Java Lang Architects 倾向于这样说 'java does not break backwards compatibility' 但这是一个严重的过度简化和边缘谎言。如果你问得更远一点,他们最终会承认这不是真的:问题的核心是 java 权衡任何向后中断的成本(它的可能性有多大,以及破坏它的代码会发生什么? 如果它仍然默默地编译和运行但做了错误的事情,那太可怕了,如果它是一个重构脚本每次都可以自动应用的微不足道的更新,那就太好了 - 然后混合任何给定代码库偶然发现它的可能性,并且你有一个想法 'cost'),对比它的好处。

这里的成本非常小。任何代码库都不太可能被破坏。然而,如果你真的想提出这个功能,那么做一些研究并尝试考虑任何图书馆会有很大帮助(或者如果你不能,看看前 100 个名单,各种人的博客,分析例如 github java projects as source material) 进行一系列尝试,看看 .isEmpty 发生的事情是否会用这些方法发生。

然后,有一些坏消息:提出 java 功能极不可能成功。从某种角度来看,作为 Project Lombok 的作者,他花费数百小时阅读像 lambda-dev 这样的邮件列表,贡献了大部分实际的 lambda 语法和概念基础,并与多个 Java 语言架构师(主要是在 java 会议上),我已经提交了一份提案,其中包括 java 本身的完整补丁,以及 JLS 所需的所有应有更新,但没有'完全破坏了向后兼容性,而且它从来没有到任何地方。甚至连 JEP 都算不上。

上次我与一位 Oracle 工程师交谈时,他们确实承诺现在情况有所好转,但这并没有特别远:我不知道周围或附近有任何 java 功能horizon 是由一个局外人提供的,他被直接踢到 JEP 并且在过去 10 年中接近可预见的 horizon 的 java 功能。有时会有人(通常是 Joe Darcy 或 Alex Buckley)运行一个 'add a bunch of small convenient language changes' 的项目,例如 Project Coin (that was 11 years ago, oof). The second take on this is Project Amber,我认为这是一个更连续的项目,而不是具有特定 Project Coin (that was 11 years ago, oof). The second take on this is Project Amber 的硬币。 =49=]时间跨度。

进入 java 的路线大概会经过 amber。