详解Java8特性之接口默认方法

来源:互联网 发布:数据库编程题 编辑:程序博客网 时间:2024/05/29 15:30

是什么

Java8中新增了接口的默认方法,简单来说就是让接口可以自己有实现方法,不许要实现类去实现。

有什么用

想象一种情况,你定义了一个接口A,假如里面有几个抽象方法。然后什么B,C,D,E…一大堆类去实现了A接口里面的几个抽象方法。那么现在问题来了,如果要在A中新加一个抽象方法,那么所有的实现类都要去实现这个抽象方法,不是很麻烦吗?这个时候默认方法就派上用场了,只需要再A中自己实现这个新添加的方法就好了,所有的实现类也可以用了。最典型的例子,Iterable接口就增加了这么一个默认方法

default void forEach(Consumer<? super T> action) {    Objects.requireNonNull(action);    for (T t : this) {        action.accept(t);    }}

我们就可以这么使用该默认方法迭代打印集合中的元素

List<Integer> integers = new ArrayList<Integer>();integers.add(1);integers.add(2);integers.add(3);integers.forEach(System.out::println);

怎么用

接口的默认方法

接口的默认方法定义很简单,就是在方法返回值前使用 default 关键字修饰,如下面这个接口

public interface MyFunction<T> {    void fun(T t);    //默认方法    default String getUpperCase(String str){        return str.toUpperCase();    }    //默认方法    default Integer getAge(){        return 23;    }}

使用也是很简单,创建一个MyFunction的实例,然后像普通实例方法的调用方式调用即可

MyFunction<String> function = System.out::println;String str = function.getUpperCase("abc");Integer age = function.getAge();function.fun("This is demo...");System.out.println("str : "+str);System.out.println("age : "+age);

输出结果

This is demo...str : ABCage : 23

接口的静态方法

Java8还允许接口中有静态方法,如

public interface MyFunction<T> {    void fun(T t);    static Integer toInteger(String num){        return Integer.parseInt(num);    }}

接口静态方法调用比较简单,类名.方法 即可调用,如

Integer num = MyFunction.toInteger("3");System.out.println(num);//3

一些规矩

如果一个接口继承了另外一个接口,而这两个接口有一个相同方法签名的默认方法,那么父接口的默认方法会被覆盖。如下面的例子

Father2接口

public interface Father2 {    default String getName(){        return "Father2";    }}

Father1接口,继承了Father2接口,他们有一个方法签名一样的默认方法getName

public interface Father1 extends Father2{    default String getName(){        return "Father1";    }}

Son类,实现Father1接口

public class Son implements Father1{}

测试类

public class Main{    public static void main(String[] args) {        Son son = new Son();        String name = son.getName();        System.out.println(name);    }}

最终输出结果为Father1,可见Father2的默认方法被Father1给覆盖了。

还有另外一个关于接口冲突规矩,现在把上面的接口和类改一下,Father2接口不变,Father1接口不再继承Father2Son类同时实现Father1Father2,你就会发现编译报错,其实就是相同的默认方法有两个,不知道用哪个,这个时候你就必须实现getName默认方法,如

public class Son implements Father1,Father2{    @Override    public String getName() {        return Father1.super.getName();    }}

在这个实现中,可以发现可以用Father1.super.getName()去调用Father1接口的默认方法,当然也可以调用Father1接口的默认方法,只需Father2.super.getName(),可以发现子类调用某个父接口的默认方法可以通过 父接口.super.方法这种格式调用。

1 0
原创粉丝点击