Java随笔 - Java 8特性之接口中的default方法和其他类、接口定义方法冲突

Java 1.8 引入一个新的特性. 接口中定义的方法可以使用 default 关键字提供默认的缺省实现.

这项新特性很便捷的帮助开发者在不修改接口的实现类的前提下,达到扩展功能的目的。可以说是非常的方便。但是这项特性带来便利的同时, 也带来了一些困惑。本文章记录笔者通过实例逐步学习这项变动的过程。

目录

  1. Q1. Java 8 之前继承多个接口. 且父接口中定义的方法有冲突
  2. Q2: Java 8 之后继承多个接口. 且父接口中定义的方法有冲突
  3. Q3. 继承类和实现接口共存的情况
  4. 总结

Q1. Java 8 之前继承多个接口. 且父接口中定义的方法有冲突

类结构如下图:

类结构图

示例代码:

1
2
3
4
5
6
7
8
9
10
11
public interface A {
    void print(String str);
}

public interface B {
    void print(String str);
}

public interface C extends A, B {

}

上述代码能编译通过。对 C 接口来讲. 父接口中定义的方法都没有具体的逻辑实现, 仅有一个定义。所以不会引起编译冲突. 子类必须实现接口定义的方法.

Q2: Java 8 之后继承多个接口. 且父接口中定义的方法有冲突

而 Java 8 之后,接口中定义了冲突的方法,且有 default 实现时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public interface A {
    default void print(String str) {
        System.out.println("A");
    }
}

public interface B {
    default void print(String str) {
        System.out.println("B");
    }
}

public interface C extends A, B {

    /**
     * <strong>必须重写父类的方法. 否则编译报错</strong>
     */
    @Override
    default void print(String str) {
        //  ...do something
    }
}

结论: 当接口 A 和接口 B 任意一个有 default 实现时. 接口 C 必须 Override 接口中的冲突的方法.

可以通过 A.super.print(str)B.super.print(str) 来分别指定要继承的默认实现. 示例:C 的 print 方法的 default 实现。先执行 A 再执行 B

1
2
3
4
5
6
7
8
9
10
public interface C extends A, B {
    /**
     * <strong>必须重写父类的方法</strong>
     */
    @Override
    default void print(String str) {
        A.super.print(str);
        B.super.print(str);
    }
}

Q3. 继承类和实现接口共存的情况

类结构如下图:

类结构图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class A {
    public void print(String str) {
        System.out.println("A");
    }
}

public interface B {
    default void print(String str) {
        System.out.println("B");
    }
}

public class C extends A implements B {

}
//  => 编译成功。输出“A”

结论: 当父类中定义的方法和接口中定义的 default 实现冲突时。隐式的采用类中的方法.

总结

  1. 当父类或接口中的定义的方法实现有冲突时, 子类必须覆写父中的方法. 或者把类定义为 abstract
  2. 当子类继承父类, 实现父接口的情况时。隐式的继承父类中的方法.
  3. 类中定义的方法实现,优先级高于接口中 default 实现

End

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 TinyZ Zzh (包含链接: https://tinyzzh.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。 如有任何疑问,请 与我联系 (tinyzzh815@gmail.com)

TinyZ Zzh

TinyZ Zzh

专注于高并发服务器、网络游戏相关(Java、PHP、Unity3D、Unreal Engine等)技术,热爱游戏事业, 正在努力实现自我价值当中。

评论

  点击开始评论...