Java实现两个接口并解决默认方法冲突:为什么使用super关键字?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java实现两个接口并解决默认方法冲突:为什么使用super关键字?相关的知识,希望对你有一定的参考价值。
Java解析默认方法冲突:为什么使用super关键字?
我正在阅读“不耐烦的核心Java SE 9”这本书。在“解决默认方法冲突”一节中,我发现在解决默认方法冲突时,会使用super关键字。但我不明白为什么要使用super
关键字。
从这个链接:https://docs.oracle.com/javase/tutorial/java/IandI/override.html我知道需要super
关键字(否则程序将无法编译)。
但这似乎违反直觉。根据我的理解,界面“Identified
”没有超级类。为什么不使用“return Identified.getId();
”?
public interface Person {
default int getId() {
return 0;
}
}
public interface Identified {
default int getId() {
return Math.abs(hashCode());
}
}
public class Employee implements Person, Identified {
public int getId() {
return Identified.super.getId();
}
}
因为Identified.getId()
意味着getId
是static
方法。在Java 8之前,这个super
关键字仅用于引用super.getId()
形式的超类。
在你的情况下,Identified.super.getId()
并不意味着“已鉴定的超级的getId()”,而是“来自已识别的超级的getId()”。
很显然,Employee
有冲突; default int getId()
和Person
的方法签名Identified
是相同的。
JLS 9.4.1.3将此描述为导致错误的行为冲突。当然,您必须决定应该调用哪个getId()
方法(覆盖它,或者从Person
或Identified
中选择默认实现。
JLS 9.4.1.1(按实例方法覆盖)提供了一个线索:
可以使用方法调用表达式(第15.12节)访问重写的默认方法,该表达式包含由超级接口名称限定的关键字。
但使用super
这个词最正式的原因来自JLS 15.12,特别是15.12.1:编译时间步骤1:确定要搜索的类或接口
本节描述了方法调用可以采用的6种形式。
一种形式是Identified.getId()
保留用于静态参考,并在另一个答案中讨论。
另一种形式是super.getId()
。这是super
这个词的更常见用法;它指的是类的超类。
这导致了15.12.1中提到的最终形式:TypeName.super.getId()
在这里,超级这个词只有一个目的。如果单词super出现在方法getId()的左侧,并且如果TypeName出现在super的左侧,则(i)TypeName必须是类或接口,(ii)如果TypeName是类,则它优先于接口,(iii)如果TypeName不是类,则它必须是接口。
所以这最终导致在这种情况下对超级的解释:
在这种情况下,超级用于匹配形式TypeName.super.identifier
,它是定义的方式(通过JLS 15.12.1)从接口TypeName调用方法标识符。
因为Indentified.getId()
语法已经用于静态方法调用。 C ++语法Identifier::getId()
本来可以很好,但Java正在使用它进行方法参考,所以不用了。无法使用Identified.this.getId()
语法,因为当您有嵌套类时,它已经用于外部类的avecà方法。
我想在某些时候他们只是没有选择。但我同意语法可能有点误导,但是因为在Java中你不能称之为“祖父母”方法,使用“超级”可能被视为较小的邪恶。
以上是关于Java实现两个接口并解决默认方法冲突:为什么使用super关键字?的主要内容,如果未能解决你的问题,请参考以下文章