Java 默认方法冲突

Java 默认方法冲突,一个类实现了两个接口,每个接口包含的默认方法相同,但实现不同。在类中实现方法。借由关键字 super,实现仍然可以使用接口提供的默认方法。Java 8 支持在接口中使用静态和默认方法。默认方法提供由类继承的实现,这使得接口可以在不破坏现有类实现的情况下添加新的方法。

Java 默认方法冲突 问题描述

一个类实现了两个接口,每个接口包含的默认方法相同,但实现不同。

Java 默认方法冲突 解决方案

在类中实现方法。借由关键字 super,实现仍然可以使用接口提供的默认方法。

Java 默认方法冲突 具体实例

Java 8 支持在接口中使用静态和默认方法。默认方法提供由类继承的实现,这使得接口可以在不破坏现有类实现的情况下添加新的方法。
由于一个类可以实现多个接口,它既可能继承具有相同签名但实现不同的默认方法,也可能已包含自己的默认方法。
此时需要考虑以下三种情况。

  • 如果类的方法和接口的默认方法发生冲突,则类的方法始终优先。
  • 如果两个接口(其中一个接口是另一个的后代)发生冲突,则后代接口优先;如果两个类(其中一个类是另一个的后代)发生冲突,则后代类优先。
  • 如果两个默认方法之间不存在继承关系,则类无法编译。

对于第三种情况,只需在类中实现方法即可,第三种情况将简化为第一种情况。
观察例 5-13 所示的 Company 接口和例 5-14 所示的 Employee 接口。

例 5-13 包含默认方法的 Company 接口

public interface Company {
    default String getName() {
        return "Initech";
    }

    // 其他方法
}

关键字 defaultgetName 方法指定为默认方法,它提供一个返回企业名称的实现。

例 5-14 包含默认方法的 Employee 接口

public interface Employee {
    String getFirst();

    String getLast();

    void convertCaffeineToCodeForMoney();

    default String getName() {
        return String.format("%s %s", getFirst(), getLast());
    }
}

Employee 接口同样定义了一个名为 getName 的默认方法,其签名与 Company 接口中的 getName 方法相同,但二者的实现不同。如例 5-15 所示,CompanyEmployee 类实现了 CompanyEmployee 两个接口,从而导致冲突。

例 5-15 最初的 CompanyEmployee 类(无法编译)

public class CompanyEmployee implements Company, Employee {
    private String first;
    private String last;

    @Override
    public void convertCaffeineToCodeForMoney() {
        System.out.println("Coding...");
    }

    @Override
    public String getFirst() {
        return first;
    }

    @Override
    Public String getLast() {
        return last;
    }
}

由于 CompanyEmployee 类继承了与 getName 无关的默认方法,它无法编译。为解决这个问题,需要在 CompanyEmployee 类中添加用户自定义的 getName 方法,它将重写两个默认方法。
不过,借由关键字 super,仍然可以使用所提供的默认方法,如例 5-16 所示。

例 5-16 调整后的 CompanyEmployee

public class CompanyEmployee implements Company, Employee {

    @Override
    public String getName() {                                   ➊
        return String.format("%s working for %s",
            Employee.super.getName(), Company.super.getName()); ➋
    }

    // 其余代码和之前一样
}

❶ 实现 getName 方法
❷ 通过 super 访问默认实现
可以看到,CompanyEmployee 类中的 getName 方法根据 CompanyEmployee 接口定义的两个默认方法 getName 构建了一个 String
最好的消息是,这与默认方法一样复杂。读者现在已经了解了如何处理默认方法冲突。
实际上,我们还要考虑一种极端情况。如果 Company 接口定义了 getName 方法但没有将其指定为 default(也不存在相应的实现,即 getName 成为抽象方法),那么当 Employee 接口也定义了 getName 方法时,是否还会导致冲突呢?答案是肯定的。有趣的是,仍然需要在 CompanyEmployee 类中提供一个实现。
在 Java 8 之前,如果两个接口包含相同的方法且没有指定为默认方法,这并不会导致冲突,但类必须提供一个实现。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程