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

客官°小女子只卖身不卖艺 2021-09-22 12:26 318阅读 0赞

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

70

类C1有成员方法A和B

  1. public class C1 {
  2. public void A(){
  3. System.out.println("C1.A()");
  4. }
  5. public void B(){
  6. System.out.println("C1.B()");
  7. }
  8. }

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

  1. public interface I1 {
  2. void C();
  3. default void E(){
  4. System.out.println("I1.default.E()");
  5. }
  6. }

接口I2有抽象方法A

  1. public interface I2 {
  2. void A();
  3. }

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

  1. public interface I3 {
  2. default void A(){
  3. System.out.println("I3.default.A()");
  4. }
  5. default void C(){
  6. System.out.println("I3.default.C()");
  7. }
  8. }

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

  1. public interface I4 {
  2. void A();
  3. default void B(){
  4. System.out.println("I4.default.B()");
  5. }
  6. }

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

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

  1. public class MainTest extends C1 implements I1{
  2. public static void main(String[] args) {
  3. C1 c1 = new C1();
  4. c1.A();
  5. c1.B();
  6. I1 i1 = new MainTest();
  7. i1.C();
  8. i1.E();
  9. }
  10. @Override
  11. public void C() {
  12. System.out.println("I1.C()");
  13. }
  14. }

结果:

  1. C1.A()
  2. C1.B()
  3. I1.C()
  4. I1.default.E()

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

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

  1. public class MainTest extends C1 implements I2{
  2. public static void main(String[] args) {
  3. C1 c1 = new C1();
  4. c1.A();
  5. c1.B();
  6. I2 i2 = new MainTest();
  7. i2.A();
  8. }
  9. }

结果:

  1. C1.A()
  2. C1.B()
  3. C1.A()

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

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

  1. public class MainTest extends C1 implements I3{
  2. public static void main(String[] args) {
  3. C1 c1 = new C1();
  4. c1.A();
  5. c1.B();
  6. I3 i3 = new MainTest();
  7. i3.A();
  8. i3.C();
  9. }
  10. }

结果:

  1. C1.A()
  2. C1.B()
  3. C1.A()
  4. I3.default.C()

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

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

  1. public class MainTest extends C1 implements I4{
  2. public static void main(String[] args) {
  3. C1 c1 = new C1();
  4. c1.A();
  5. c1.B();
  6. I4 i4 = new MainTest();
  7. i4.A();
  8. i4.B();
  9. }
  10. }

结果:

  1. C1.A()
  2. C1.B()
  3. C1.A()
  4. C1.B()

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

  1. interface I1 {
  2. void A();
  3. default void B(){
  4. System.out.println("I1.default.B()");
  5. }
  6. }
  7. interface I2 {
  8. void A();
  9. default void B(){
  10. System.out.println("I2.default.B()");
  11. }
  12. }
  13. public class MainTest implements I1, I2{
  14. public static void main(String[] args) {
  15. MainTest mainTest = new MainTest();
  16. mainTest.B();
  17. mainTest.A();
  18. }
  19. @Override
  20. public void B() {
  21. I2.super.B();
  22. }
  23. @Override
  24. public void A() {
  25. System.out.println("A(),I don't know who I am");
  26. }
  27. }

结果:

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

总结

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

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

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

发表评论

表情:
评论列表 (有 0 条评论,318人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java8接口默认方法

    使用函数式接口Supplier来实例化接口默认方法,Supplier对于给定的泛型类型产生一个实例,不需要任何参数。 接口:DefaultMethodInterface

    相关 java8接口默认方法

    解决问题:在java8 之前的版本,在修改已有的接口的时候,需要修改实现该接口的实现类。 作用:解决接口的修改与现有的实现不兼容的问题。在不影响原有实现类的结构下修改新的功能