Java解析默认方法冲突:为什么要使用super关键字?
我正在读这本书"核心Java SE 9因为不耐烦而且#34;。在部分
"解决默认方法冲突",我发现在解决时
默认方法冲突,使用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();
}
}
答案 0 :(得分:4)
因为Identified.getId()
意味着getId
是static
方法。在Java 8之前,此super
关键字仅用于引用super.getId()
形式的超类。
在你的情况下,Identified.super.getId()
并不意味着"识别"的超级的getId(),而是"超级的getId()来自已识别"。
答案 1 :(得分:2)
很明显Employee
有冲突; default int getId()
和Person
的方法签名Identified
相同。
JLS 9.4.1.3将此描述为导致错误的行为冲突。当然,您必须决定应该调用哪个getId()
方法(覆盖它,或者从Person
或Identified
选择默认实现。
JLS 9.4.1.1(按实例方法覆盖)提供了一个线索:
可以使用方法访问重写的默认方法 包含关键字super的调用表达式(第15.12节) 由超级接口名称限定。
但使用单词super
的最正式理由来自JLS 15.12,特别是15.12.1:编译时步骤1:确定要搜索的类或接口
该部分描述了方法调用可以采用的6个表单。
一个表单Identified.getId()
保留用于静态引用,并在另一个答案中讨论。
另一种形式是super.getId()
。这是super
一词的更常见用法;它指的是类的超类。
这导致了15.12.1中提到的最终形式:TypeName.super.getId()
这里的单词super只有一个目的。如果单词super出现在方法getId()的左侧,并且如果TypeName出现在super的左侧,则(i)TypeName必须是类或接口,(ii)如果TypeName是类,则它优先于接口,(iii)如果TypeName不是类,则它必须是接口。
所以这最终导致在这种背景下对超级的解释:
超级在这种情况下用于 匹配表格 TypeName.super.identifier
,这是定义的方式(通过JLS 15.12.1)从中调用方法标识符interface TypeName。
答案 2 :(得分:1)
因为Indentified.getId()
语法已用于静态方法调用。 C ++语法Identifier::getId()
本来可以很好,但是Java正在使用它进行方法参考,所以也不行。无法使用Identified.this.getId()
语法,因为当您使用嵌套类时,它已经用于外部类的avecà方法。
我想在某些时候他们的选项已经用光了。但我同意语法可能有点误导,但是因为在Java中你不能称之为“祖父母”方法,使用“超级”可能被视为较小的邪恶。