2018-11-14 · Develop

Java8 默认方法

我们都知道在Java语言的接口中只能定义方法名,而不能包含方法的具体实现代码。接口中定义的方法必须在接口的非抽象子类中实现。因为接口有这个语法限制,所以要直接改变/扩展接口内的方法变得非常困难。

Java8 在强化 Collections API,让其支持lambda表达式的时候,就面临了这样的挑战。为了克服这个困难,Java 8中引入了一个新的概念,叫做default方法,也可以称为Defender方法,或者虚拟扩展方法(Virtual extension methods)。

Default方法是指,在接口内部包含了一些默认的方法实现(也就是接口中可以包含方法体,这打破了Java之前版本对接口的语法限制),从而使得接口在进行扩展的时候,不会破坏与接口相关的实现类代码。

网络上关于 default 方法的介绍有很多,如果你的英语可以的话,也可以查看 这篇文档 。在这里我主要讲述两个特殊的场景。

多继承

如果一个类实现了两个接口(可以看做是“多继承”),这两个接口又同时都包含了一个名字相同的default方法,那么会发生什么情况?

interface InterfaceA {

    default String say(String name) {
        return "Hello, " + name;
    }
}

interface InterfaceB {

    default String say(String name) {
        return "Hi, " + name;
    }
}

在这样的情况下,编译器会报错。那要如何解决这个问题呢?请看下面的示例代码

interface InterfaceC extends InterfaceA, InterfaceB {

    @Override
    default String say(String name) {
        return name;
    }
}

在这种“多继承”的情况下,只需要重写相同签名的方法就可以了。

调用父类的 default 方法

有些时候,我们并不希望完全进行重写父类的方法,我们还需要调用父类已经实现的方法,在这种情况下,如何调用 default 方法中的代码呢?其实很简单,通过接口名进行调用

interface InterfaceC extends InterfaceA, InterfaceB {

    @Override
    default String say(String name) {
        System.out.println(InterfaceA.super.say(name));
        System.out.println(InterfaceB.super.say(name));
        return name;
    }
}

参考文档

Java 8新特性——default方法(defender方法)介绍