JDK8接口新特性:默认方法

2018-09-01  本文已影响0人  某程序猿

默认方法

在jdk8中关于接口新增一个特性,就是interface可以有默认方法。
例如定义一个Named接口:

public interface Named {
    default String getName() {
        return "nathan, by default";
    }
}

假如你是1.8以下版本,这样写肯定连编译都通不过。可能有都同学会问,接口又不能实例化,增加这个方法都意义何在?在以往的java API中包含了很多伴随方法,如Collection/AbstractCollection,AbstractCollection实现了Collection中的部分方法。在jdk8中,就不需要这么做,直接使用default 关键字就能实现默认方法了,这样会使得代码结构更加精简。
现在我们来实现这个接口,定义一个NameNobody,但是不实现该方法:

public class NamedNobody implements Named {
}

接下来编写一个测试类:

public class Main {

    public static void main(String[] args) {
        Named named = new NamedNobody();
        System.out.println(named.getName()); // nathan, by default
    }
}

执行结果:

nathan, by default

可以看到即使没有实现接口方法,也会自动调用接口内的默认实现。

方法冲突

大家都知道,java是允许一个类同时实现多个接口的,现在有一个Person接口,也有一个getName方法

public interface Person {

    default String getName() {
        return "Person, by default";
    }
}

然后有一个Student类同时实现了Person和Named接口

public class Student implements Named, Person {

    @Override
    public String getName() {
        return "student";
    }
}

此时Student必须实现getName方法,否则编译不通过。

public class Main {

    public static void main(String[] args) {
        Named student = new Student();
        System.out.println(student.getName());
    }
}

执行结果:

student

我们接下来看更一个更复杂的情况,有NamedPerson类,拥有一个getName方法

public class NamedPerson {

    public String getName() {
        return "NamedPerson";
    }
}

还有个Staff类,继承了NamedPerson,实现了Named接口

public class Staff extends NamedPerson implements Named {

}

此时不实现Named中的抽象方法也不会报错,我们来运行以下看看:

public class Main {

    public static void main(String[] args) {
        Staff staff = new Staff();
        System.out.println(staff.getName());
    }
}

执行结果:

NamedPerson

可以看到实际调用的是父类中的方法。


结构图.png

上图是整个demo的继承关系。
通过上面两个例子,我们可以总结出两条解决冲突的规则:

上一篇 下一篇

猜你喜欢

热点阅读