为什么Delayed没有提供compareTo的默认方法?

3
接口Delayed要求任何实现该接口的类都需要定义一个compareTo方法,以便与其getDelay方法提供一致的排序。然而,我想知道为什么在Java 8中没有默认实现,因为按合同要求,compareTo只依赖于getDelay。这是因为留给实现类吗?还是在覆盖超级接口时无法创建默认方法?编辑:为了使我的问题更容易理解,这里有一个例子:
interface Delayed extends Comparable<Delayed> {

    long getDelay(TimeUnit unit);

    @Override
    default int compareTo(Delayed o) {
      // might not be the perfect "compareTo" implementation, but you get the point
      return o == this? 0:
        Long.compare(this.getDelay(TimeUnit.NANOSECONDS), o.getDelay(TimeUnit.NANOSECONDS);
    }

}

2
默认实现如何获取必要的“对象状态”以执行计算?接口没有状态! - fge
1
不仅如此,compareTo 方法高度特定于一个类。你会按照什么来排序一个 Object 呢?它的引用?它的 toString?它的 hashcode? - Powerlord
1
如上所述,@fge和@Powerlord,“compareTo”方法必须根据“getDelay”提供排序,不需要其他信息。据我所知,默认方法可以自由调用任何兄弟方法,或者我错了吗? - Sebastian S
1
你没有错,但是 .getDelay() 的合约本身意味着如果延迟已经过期,那么可以违反 Comparable 合约。 - fge
3
合同描述不清楚。合同仅仅表示0或负值意味着延迟已经过期,但不清楚如果延迟已过期,Delayed 是否可以返回任何<= 0的值,如果两个已过期的 Delayed 应该被视为相等,或者 Delayed 是否必须按自然、时间轴的方式进行演变(例如在限制后1分钟,它应该返回-1分钟)。 - JB Nizet
显示剩余4条评论
1个回答

5
简而言之,Delayed 自1.5版本开始存在,default 方法自1.8版本开始存在。因此,为了将 compareTo 方法作为 default 方法提供,必须有意地更改接口。

如果没有发生这种情况,可能有以下几个原因:

  • 可能只是没有人考虑过
  • 可能已经考虑过,但被放弃了,因为:

    • 可能存在兼容性问题
    • 预期的收益不足以证明API更改的必要性
    • 在发布之前有更高优先级的事情要做

对我来说,这似乎不是一个高优先级的问题。大多数情况下,您会在JRE提供的ScheduledExecutorService上下文中遇到Delayed实现,并且这些实现已经存在,因此不会从这样的更改中受益。

我不认为您会经常在应用程序代码中遇到自定义Delayed实现,但即使您看到它与其他显然更有用的添加相比,JRE开发人员显然决定集中精力添加(或较少争议的)更有用的功能。


思考一下,结合有关 getDelay() 合同和 Comparable 合同时的 讨论,如果 Delayed 根本不扩展 Comparable 就更好了。毕竟,使用 Comparator 或类似的设计模式按属性对对象进行排序并不难。

1
Occam的剃刀原则建议我接受这个理由,直到有人提供更好的理由。 - Sebastian S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接