Java8中接口中默认方法如何解决冲突?

前置知识

Java中的多态应该都不陌生,这一特性是通过继承父类或者实现父接口来展现的。但是父类或者父接口中定义的方法可能不能满足新需求了。那么很容易想到在原始类中添加方法,但是子类或者实现类都需要变动,显然是相当难维护,为了解决这个问题,Java 8允许在接口内声明静态方法,且允许接口中定义默认方法(default关键字)。

这里所说的重点就是引进了default之后,如果某一个具体类 实现了多个具有相同的签名的默认方法之后,Java8 是如何解决冲突的?

解决冲突的规则

  1. 类中的方法优先级最高。类和父类中的方法优先于其他类。
  2. 如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。
  3. 最后,如果还是无法判断,继承了多个接口的类必须通过显式覆盖和调用期望的方法,显式地选择使用哪一个默认方法的实现。

案例

规则一

    public interface A {
        default void hello() {
            System.out.println("Hello from A");
        }
    }
    
    public class D implements A{
		void hello() {
            System.out.println("Hello from D");
        }
	}
    
    public interface B extends A {
        default void hello() {
            System.out.println("Hello from B");
        }
    }
    public class C extends D implements B, A {
        public static void main(String... args) {
            new C().hello();
        }
    }

由于有继承关系,所以按照规则1先进行查找,C类继承自D,而D含有A接口hello方法的重写,所以这里打印"Hello from D"


规则2

    public interface A {
        default void hello() {
            System.out.println("Hello from A");
        }
    }
    
    public class D implements A{}
    
    public interface B extends A {
        @Override
        default void hello() {
            System.out.println("Hello from B");
        }
    }
    public class C extends D implements B, A {
        public static void main(String... args) {
            new C().hello();
        }
    }

由于有继承关系,所以按照规则1先进行查找,C类继承自D,而D没覆盖hello方法,所以只能拥有接口A的hello方法的默认实现,所以C现在拥有了A接口的hello;规则(2)说如果类或者父类没有对应的方法,那么就应该选择提供了最具体实现的接口中的方法。而这里C实现了B,发现B中更加具体(B中hello是对A接口hello的实现),所以程序会再次打印输出“Hello from B”


规则3

如下所示,这里没有哪个接口的hello更具体

    public interface A {
        void hello() {
            System.out.println("Hello from A");
        }
    }
    public interface B {
        void hello() {
            System.out.println("Hello from B");
        }
    }
    // 显式消除
    public class C implements B, A {
        void hello(){
            B.super.hello();
        }
    }

通过在C中显示覆盖hello 指定调用谁的hello方法。

附录

菱形继承问题

    public interface A{
        default void hello(){
            System.out.println("Hello from A");
        }
    }
    public interface B extends A { }
    public interface C extends A { }
    public class D implements B, C {
        public static void main(String... args) {
            new D().hello();
        }
    }

其继承关系如下所示:
<img src="./images/1667231377987.jpg />

因为继承关系如菱形,所以被称为菱形问题。

只有A声明了一个默认方法。由于这个接口是D的父接口,代码会打印输出“Hello from A”

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值