Java 在接口中默认参数

简介

在 Java 8 中,引入了一个新特性,允许在接口中定义默认方法。默认方法是指在接口中提供了方法的实现,且可以在子类中直接使用,而无需实现该方法。这个特性的引入解决了一个问题,即当我们需要在接口中新增一个方法时,由于现有的实现类需要实现这个方法,这将导致破坏已有的代码。

为什么需要默认方法?

在 Java 8 之前,接口中只能定义方法的签名,而不能提供方法的实现。这导致了一个严重的问题,即当需要在接口中新增一个方法时,已经实现了该接口的类需要修改代码以实现这个方法。这一问题在存在大量实现类的情况下尤为明显,修改大量代码将带来极大的困扰。

为了解决这个问题,Java 8 引入了默认方法,允许在接口中提供方法的默认实现。这样,所有实现了该接口的类都可以直接使用默认实现,而无需修改任何代码。

接口中的默认方法

接口中的默认方法使用 default 关键字进行修饰。以下是一个简单的例子:

public interface Greeting {
    // 默认方法
    default void sayHello() {
        System.out.println("Hello, World!");
    }
}

在上面的例子中,我们定义了一个接口 Greeting,其中包含一个默认方法 sayHello()。该方法的实现是打印出 "Hello, World!"。

接下来,我们可以实现这个接口并直接使用默认方法:

public class EnglishGreeting implements Greeting {
    public static void main(String[] args) {
        EnglishGreeting greeting = new EnglishGreeting();
        greeting.sayHello(); // 输出 "Hello, World!"
    }
}

在上面的例子中,我们创建了一个 EnglishGreeting 类,实现了 Greeting 接口,并直接调用了 sayHello() 方法。由于 Greeting 接口中已经提供了 sayHello() 的默认实现,所以我们可以直接使用。

默认方法的优先级

当一个类实现了多个接口,并且这些接口中有相同的默认方法时,编译器会产生一个冲突。为了解决这个问题,我们可以通过以下方式之一:

  • 类优先:如果一个类实现了一个接口,并且实现了相同的默认方法,那么类中的方法将覆盖接口中的方法。
  • 接口冲突解决:如果一个类实现了多个接口,并且这些接口有相同的默认方法,那么我们需要在类中覆盖这个默认方法,并指定应该调用哪个接口的方法。

下面是一个示例:

public interface A {
    default void sayHello() {
        System.out.println("Hello from A");
    }
}

public interface B {
    default void sayHello() {
        System.out.println("Hello from B");
    }
}

public class C implements A, B {
    public static void main(String[] args) {
        C c = new C();
        c.sayHello(); // 编译错误,需要在 C 类中覆盖 sayHello() 方法
    }

    @Override
    public void sayHello() {
        A.super.sayHello(); // 调用接口 A 的默认方法
    }
}

在上面的示例中,接口 AB 都提供了一个默认方法 sayHello()。当我们在 C 类中实现这两个接口时,编译器会报错,因为它无法决定使用哪个默认方法。

为了解决这个问题,我们在 C 类中覆盖了 sayHello() 方法,并指定了应该调用接口 A 的默认方法。

序列图

为了更好地理解接口中默认方法的使用,我们可以使用序列图来说明这一过程。

sequenceDiagram
    participant Interface as I
    participant Class as C
    participant Implementation as Impl
    
    C->>I: implements
    Impl->>I: implements
    Impl->>C: uses
    
    Note over I, C: Default