Java接口中的默认方法
Java 8及更高版本已将新功能添加到Java接口中,称为Java接口中的默认方法。通过包含默认方法,Java中的接口可以具有方法的默认实现。注意,在通常的传统接口形式中,所有方法都是抽象的,没有主体,现在有了默认方法,我们甚至可以在接口中使用方法实现。
如何定义默认方法
要在Java中定义接口默认方法,我们需要在方法签名中使用default关键字。
接口默认方法语法
default return_type methodName(arguments) { .. .. }
为什么界面中包含默认方法
接口中包含默认方法,使接口易于演化而不会破坏现有的实现。
例如,假设有一个库,其中有一个由许多类实现的接口。现在,已经发布了新版本的库,并在接口中包含了用于新功能的新方法。
即使不需要该新功能,使用该接口的新版本的任何类都必须实施该新方法。使用Java接口中的默认方法,实现该接口的类可以使用默认实现本身,而不必强迫提供其自己的实现。
Java接口默认方法示例
public interface MyInterface { int add(int a, int b); // interface default method default void showMessage(String msg) { System.out.println("Default method message- " + msg); } }
接口MyInterface具有一种抽象方法和一种默认方法。因此,实现此接口的类必须实现add()方法,该方法是抽象的,但可以自由使用showMessage()方法的默认实现。
public class MainClass implements MyInterface{ @Override public int add(int a, int b) { return a + b; } public static void main(String[] args) { MainClass obj = new MainClass(); int result = obj.add(14, 22); System.out.println("result- " + result); // using default method in the interface obj.showMessage("Use the default method implementation"); } }
输出:
result- 36 Default method message- Use the default method implementation
实现接口默认方法
实现类还可以提供自己的默认方法实现,而不是使用默认方法。
public class MainClass implements MyInterface{ @Override public int add(int a, int b) { return a + b; } /// Overriding default method public void showMessage(String msg) { System.out.println("Class implementation message- " + msg); } public static void main(String[] args) { MainClass obj = new MainClass(); int result = obj.add(14, 22); System.out.println("result- " + result); obj.showMessage("Use the method implementation in the class"); } }
输出:
result- 36 Class implementation message- Use the method implementation in the class
Java默认方法–解决多重继承问题
如果一个类实现两个接口,并且这两个接口都具有一个具有相同名称和相同数量参数的方法,并且至少其中一个是默认方法(或者两者),则将发生冲突。
让我们看一个例子,使之更清楚。有两个接口,并且两个接口都有一个具有相同签名的showMessage()方法。在其中一个接口中,showMessage()被声明为默认接口,而在另一个接口中,它是一个抽象方法。
public interface MyInterface { int add(int a, int b); // interface default method default void showMessage(String msg) { System.out.println("Default method message- " + msg); } } interface MySecondInterface { void showMessage(String msg); }
public class MainClass implements MyInterface, MySecondInterface{ @Override public int add(int a, int b) { return a + b; } public static void main(String[] args) { MainClass obj = new MainClass(); int result = obj.add(14, 22); System.out.println("result- " + result); obj.showMessage("Use the method implementation in the class"); } }
如果类如上所述实现了这两个接口,则将出现编译时错误"从MyInterface继承的默认方法showMessage(String)与从MySecondInterface继承的另一个方法冲突"。出现此错误的原因是编译器无法决定要使用这两种方法中的哪一种。
要解决此问题,有两种选择
实现接口的类都应提供其自己的方法实现。
使用super关键字在接口中调用默认方法。在以上示例中,仅在一个接口中默认使用方法,因此只能使用super调用该方法。
实现类提供自己的实现
public class MainClass implements MyInterface, MySecondInterface{ @Override public int add(int a, int b) { return a + b; } public void showMessage(String msg) { System.out.println("Class implementation message- " + msg); } public static void main(String[] args) { MainClass obj = new MainClass(); int result = obj.add(14, 22); System.out.println("result- " + result); obj.showMessage("Use the method implementation in the class"); } }
使用超级委托
public class MainClass implements MyInterface, MySecondInterface{ @Override public int add(int a, int b) { return a + b; } public void showMessage(String msg) { MyInterface.super.showMessage("calling interface method"); } public static void main(String[] args) { MainClass obj = new MainClass(); int result = obj.add(14, 22); System.out.println("result- " + result); obj.showMessage("Use the method implementation in the class"); } }
请注意,无论哪种情况,实现类都必须提供showMessage()方法(冲突方法)。
扩展具有默认方法的接口
我们一定知道一个接口可以扩展另一个接口。在这种情况下,如果超级接口包含默认方法,则也有某些规则。
如果子界面未提及默认方法,则它将继承默认方法。
如果子接口重新声明了默认方法,则该方法将变为抽象方法。在那种情况下,任何实现子接口的类都必须提供该方法的实现。
在子界面中,重新定义默认方法,该方法将覆盖它。
例如,存在一个带有默认方法showMessage()的接口MyInterface,以及另一个扩展了MyInterface的接口MySecondInterface。在MySecondInterface中,再次声明showMessage()方法,从而使其成为抽象方法。
public interface MyInterface { int add(int a, int b); // interface default method default void showMessage(String msg) { System.out.println("Default method message- " + msg); } } interface MySecondInterface extends MyInterface { void showMessage(String msg); }
在这种情况下,实现MySecondInterface的类必须为showMessage()方法提供实现,因为它是该接口中的抽象方法。
public class MainClass implements MySecondInterface{ @Override public int add(int a, int b) { return a + b; } @Override public void showMessage(String msg) { System.out.println("Message- " + msg); } public static void main(String[] args) { MainClass obj = new MainClass(); int result = obj.add(14, 22); System.out.println("result- " + result); obj.showMessage("Use the method implementation in the class"); } }
在扩展界面中重新定义默认方法
public interface MyInterface { int add(int a, int b); // interface default method default void showMessage(String msg) { System.out.println("Default method in MyInterface message- " + msg); } } interface MySecondInterface extends MyInterface { default void showMessage(String msg) { System.out.println("Default method in MySecondInterface message- " + msg); } }