Java实现两个接口并解决默认方法冲突:为什么使用super关键字?

时间:2018-03-03 04:17:23

标签: java interface multiple-inheritance

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();
    }
}

questionquestion中有一些解释,但没有解释为什么使用关键字super

3 个答案:

答案 0 :(得分:4)

因为Identified.getId()意味着getIdstatic方法。在Java 8之前,此super关键字仅用于引用super.getId()形式的超类。

在你的情况下,Identified.super.getId()并不意味着"识别"的超级的getId(),而是"超级的getId()来自已识别"。

答案 1 :(得分:2)

很明显Employee有冲突; default int getId()Person的方法签名Identified 相同

JLS 9.4.1.3将此描述为导致错误的行为冲突。当然,您必须决定应该调用哪个getId()方法(覆盖它,或者从PersonIdentified选择默认实现。

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中你不能称之为“祖父母”方法,使用“超级”可能被视为较小的邪恶。