JDK8接口新特性:默认方法

默认方法

在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的继承关系。
通过上面两个例子,我们可以总结出两条解决冲突的规则:

  • 接口冲突:如果一个类同时实现了具有相同方法签名的接口,则该类必须覆盖该抽象方法。
  • 超类冲突:超类和接口提供相同方法签名的方法,此时子类要是不覆盖,则默认调用超类方法。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容