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 的默认方法
}
}
在上面的示例中,接口 A
和 B
都提供了一个默认方法 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