当前位置: 首页 > 面试题库 >

Java8:为什么禁止为java.lang.Object中的方法定义默认方法

匡安宜
2023-03-14
问题内容

默认方法是Java工具箱中一个不错的新工具。但是,我试图编写一个定义方法default版本的接口toString。Java告诉我,这是禁止的,因为in中声明的方法java.lang.Object可能无法default编辑。为什么会这样呢?

我知道有一个“基类始终获胜”规则,因此默认情况下(pun;),方法的任何default实现Object都会被该方法覆盖Object。但是,我认为没有理由为什么Object规范中的方法不应有例外。特别是因为toString它具有默认实现可能非常有用。

那么,Java设计者决定不允许default方法覆盖方法的原因是什么Object


问题答案:

这是语言设计中的另一个问题,在你开始挖掘并且意识到这实际上是一个坏主意之前,这似乎是“显然是个好主意”。

这封邮件涉及很多主题(以及其他主题。)有多种设计力量融合在一起,使我们进入了当前的设计:

  • 保持继承模型简单的愿望;
  • 一旦你查看了明显的示例(例如,AbstractList变成一个接口),便意识到继承equals / hashCode / toString与单继承和状态紧密相关,并且接口被多重继承且为无状态。
  • 它可能为某些令人惊讶的行为打开了大门。
    你已经达到了“保持简单”的目标。继承和冲突解决规则的设计非常简单(类胜于接口,派生接口胜于超接口,其他任何冲突都由实现类解决。)当然,可以对这些规则进行调整以使其成为异常,但是我想你会发现,当你开始使用该字符串时,增量复杂性并没有你想象的那么小。

当然,有一定程度的好处可以证明更加复杂,但是这种情况并不存在。我们在这里讨论的方法是equals,hashCode和toString。这些方法本质上都是关于对象状态的,并且拥有状态而不是接口的类是确定状态对该类意味着什么的最佳位置(特别是当平等的契约非常牢固时;请参见有效)。 Java带来一些令人惊讶的后果);接口编写器距离太远了。

AbstractList举个例子很容易。如果我们可以摆脱该问题AbstractList并将其放入List界面中,那将是很可爱的。但是,一旦你超越了这个显而易见的示例,就找不到很多其他好的示例。从根本上说,AbstractList它是为单一继承而设计的。但是接口必须设计用于多重继承。

进一步,假设你正在编写此类:

class Foo implements com.libraryA.Bar, com.libraryB.Moo { 
    // Implementation of Foo, that does NOT override equals
}

该Foo作家着眼于超类型,认为没有实现平等的,并得出结论,得到参考平等,所有他所要做的就是继承平等Object。然后,下周,“有帮助”的Bar库维护者添加了默认equals实现。哎呀!现在,的语义Foo已被另一个维护域中的接口“有帮助地”破坏了,为通用方法添加了默认值。

默认值应该是默认值。向没有接口(层次结构中的任何地方)的接口添加默认值不应影响具体实现类的语义。但是如果默认值可以“覆盖” Object方法,那将不是事实。

因此,尽管它看起来像是一种无害的功能,但实际上却是相当有害的:它增加了很多复杂性,几乎没有增量表达能力,而且对于原本意图良好,无害的更改进行单独编译的界面,破坏太容易了。实现类的预期语义。



 类似资料:
  • 默认方法是Java工具箱中一个很好的新工具。然而,我试图编写一个接口,定义方法的版本。Java告诉我这是禁止的,因为方法是在可能不是默认值。为什么会是这种情况? 我知道有“基类总是赢”的规则,所以默认情况下(双关语;),方法的任何实现都将被中的方法覆盖。但是,我看不出规范中的中的方法不应该有例外的原因。特别是对于来说,拥有一个默认实现可能非常有用。 那么,Java设计人员决定不允许方法重写中的方法

  • 我们举个例子: 一个常见的解决方案是转移到一个抽象类,但是在我的具体案例中,我有一个枚举的接口,所以在这里不适用。我想这不是被忽略了,就是因为接口背后的原始想法,即它们是可用方法的“契约”,但我想我需要关于这是怎么回事的输入。 我读过“为什么Java 8接口方法中不允许使用”final“?”,其中说: 默认方法的基本思想是:它是具有默认实现的接口方法,派生类可以提供更具体的实现 与关联问题一样,由

  • 主要内容:1 Java8 默认方法的介绍,2 Java8 默认方法的案例1 Java8 默认方法的介绍 Java提供了一种在接口内部创建默认方法的功能。在接口内部定义并带有默认标记的方法称为默认方法。这些方法是非抽象方法。 2 Java8 默认方法的案例 在下面的示例中,Sayable是一个功能接口,其中包含默认值和抽象方法。默认方法的概念用于定义具有默认实现的方法。您还可以覆盖默认方法,以为该方法提供更具体的实现。 输出结果为:  

  • 学习Java8默认方法。这个链接就像互联网上的其他资源一样说 在“最严格的意义上”,默认方法是一种倒退,因为它们允许你用代码“污染”你的接口。但它们提供了允许向后兼容的最优雅和最实用的方法。它使Oracle更容易更新所有集合类,也使您更容易为Lambda修改现有代码。 我的理解是Java8Dev/Designers在接口中提供了默认方法,这样所有实现类就不必不必要地重写相同的行为,从而提供了向后兼

  • 在Java8中使用缺省方法作为穷人版本的traits是一种安全的做法吗? 有人说,如果你只是为了熊猫而使用它们,可能会让熊猫伤心,因为它很酷,但这不是我的本意。人们还经常提醒说,引入缺省方法是为了支持API演进和向后兼容性,这是真的,但这并不使使用它们作为特征本身是错误的或扭曲的。 我脑海中有以下实际用例: 或者,定义: 关于SO的几个问题与Java vs Scala特性有关;这不是重点。我也不仅

  • 问题内容: 出于好奇, 为什么将方法的访问修饰符设置为。为什么不能呢?有人可以向我解释这背后的任何具体原因吗? 另外,我知道该方法仅被调用一次。如果我在程序内部两次调用它,会发生什么情况?垃圾收集器会再次调用吗? 问题答案: 我用另一个问题回答您的问题: 为什么方法不应该受到保护? 通常,您应该尝试使事物尽可能私密。这就是封装的全部意义所在。否则,您 什么都 可以做。不能(因为派生类应该能够访问它