Java接口中的默认方法

时间:2020-01-09 10:34:52  来源:igfitidea点击:

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