JAVA 8 接口默认方法 - 多级实现分析

现在有这么一些场景,如下面表格所述,假设具体类及接口的权限修饰符都为`public`

类C1有成员方法A和B

public class C1 {
	public void A(){
		System.out.println("C1.A()");
	}
	public void B(){
		System.out.println("C1.B()");
	}
}

接口I1有抽象方法C以及默认方法D

public interface I1 {
	void C();
	default void E(){
		System.out.println("I1.default.E()");
	}
}

接口I2有抽象方法A

public interface I2 {
	void A();
}

接口I3有默认方法A以及默认方法C

public interface I3 {
	default void A(){
		System.out.println("I3.default.A()");
	}
	default void C(){
		System.out.println("I3.default.C()");
	}
}

接口I4有抽象方法A以及默认方法B

public interface I4 {
	void A();
	default void B(){
		System.out.println("I4.default.B()");
	}
}

(与上表相同,复制到这里为了方便阅读)

场景一:定义类MainTest继承类C1实现接口I1,因为类C1以及接口I1中所有的方法签名都不一样,所以调用时不考虑方法签名重复问题

public class MainTest extends C1 implements I1{

	public static void main(String[] args) {
		
		C1 c1 = new C1();
		c1.A();
		c1.B();
		
		I1 i1 = new MainTest();
		i1.C();
		i1.E();
		
	}

	@Override
	public void C() {
		System.out.println("I1.C()");
	}
	
}

结果:

C1.A()
C1.B()
I1.C()
I1.default.E()

(与上表相同,复制到这里为了方便阅读)

场景二:定义类MainTest继承类C1实现接口I2,I2抽象方法A与类成员方法A签名重复,优先使用父类方法

public class MainTest extends C1 implements I2{

	public static void main(String[] args) {
		
		C1 c1 = new C1();
		c1.A();
		c1.B();
		
		I2 i2 = new MainTest();
		i2.A();
		
	}

}

结果:

C1.A()
C1.B()
C1.A()

(与上表相同,复制到这里为了方便阅读)

场景三:定义类MainTest继承类C1实现接口I3,接口I3默认方法A签名与类C1成员方法A签名重复,优先使用父类成员方法

public class MainTest extends C1 implements I3{

	public static void main(String[] args) {
		
		C1 c1 = new C1();
		c1.A();
		c1.B();
		
		I3 i3 = new MainTest();
		i3.A();
		i3.C();
	}

}

结果:

C1.A()
C1.B()
C1.A()
I3.default.C()

(与上表相同,复制到这里为了方便阅读)

场景四:定义类MainTest继承类C1实现接口I4,接口I4方法A、B的签名分别与类C1的方法A、B签名重复,优先使用父类方法

public class MainTest extends C1 implements I4{

	public static void main(String[] args) {
		
		C1 c1 = new C1();
		c1.A();
		c1.B();
		
		I4 i4 = new MainTest();
		i4.A();
		i4.B();
	}

}

结果:

C1.A()
C1.B()
C1.A()
C1.B()

场景五:假如一个接口I1的抽象方法、默认方法都与接口I2的抽象方法、默认方法的签名一样,当实现的多个接口中有相同签名的方法时,必须在实现类中通过重写方法解决冲突问题,否则无法通过编译,在重写的方法中可以通过 接口名.super.方法名(); 的方式显示调用需要的方法

interface I1 {

	void A();
	
	default void B(){
		System.out.println("I1.default.B()");
	}
	
}

interface I2 {

	void A();
	
	default void B(){
		System.out.println("I2.default.B()");
	}
}

public class MainTest implements I1, I2{

	public static void main(String[] args) {
		
		MainTest mainTest = new MainTest();
		mainTest.B();
		mainTest.A();
		
	}

	@Override
	public void B() {
		I2.super.B();
	}

	@Override
	public void A() {
		System.out.println("A(),I don't know who I am");
	}

}

结果:

I2.default.B()
A(),I don't know who I am

总结

1.当继承的父类和实现的接口中有相同签名的方法,优先使用父类的方法

2.当实现的多个接口中有相同签名的方法时,必须在实现类中通过重写方法解决冲突问题,否则无法通过编译,在重写的方法中可以通过 接口名.super.方法名(); 的方式显示调用需要的方法

3.当接口的父接口中也有同样的默认方法时,就近原则调用子接口的方法。

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值