Java8 接口的默认方法

使用 default 关键字为接口定义默认方法(有实现的方法)

  • 抽象方法,接口的子类需要实现
  • 默认方法,接口的子类不需要实现,可以直接使用
  • 可以定义一个或多个默认方法

使用:

public class InterfaceWithDefaultMethod {
    public static void main(String[] args) throws Exception {
        // 匿名类
        MyInterface mi = new MyInterface() {
            public void f1() {
                System.out.println("f1");
            }
        };

        mi.f1();
        mi.f2(); // 子类可以直接使用默认方法
    }
}

interface MyInterface {
    void f1();

    default void f2() {
        System.out.println("f2");
    }
}

接口的子类也可以实现默认方法,即重写(override)默认方法,例如:

public class InterfaceWithDefaultMethod {
    public static void main(String[] args) throws Exception {
        MyInterface mi = new MyInterface() {
            public void f1() {
                System.out.println("f1");
            }
            // 接口的子类也可以实现默认方法
            public void f2() {
                System.out.println("new f2");
            }
        };

        mi.f1();
        mi.f2();
    }
}

interface MyInterface {
    void f1();

    default void f2() {
        System.out.println("f2");
    }
}

多重继承的问题

观察以下代码,会出现编译错误:

java: class InterfaceC inherits unrelated defaults for f() from types InterfaceA and InterfaceB

interface InterfaceA {
    default void f() {}
}

interface InterfaceB {
    default void f() {}
}

class InterfaceC implements InterfaceA, InterfaceB {
    
}

为了解决以上的冲突,需要手动重写(override)默认方法,例如:

class InterfaceC implements InterfaceA, InterfaceB {
    public void f() {
        System.out.println("my local f");
    }
}

如果我们想使用特定接口的默认方法,可以使用如下方式:

class InterfaceC implements InterfaceA, InterfaceB {
    public void f() {
        InterfaceA.super.f();
    }
}

Java库中的使用

Iterable 接口中 forEach 方法即为默认方法,可以传入一个函数式接口,即 Lambda 表达式:

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

抽象类 VS 接口(带有默认方法的接口)

相同点

  • 都可以有方法实现(Java8 之前接口不能有方法实现)
  • 子类不需要实现全部的方法(Java8 之前接口的子类需要实现全部的方法)

不同点

  • 抽象类不可以多重继承,接口可以
  • 抽象类表示的是"is-a"关系,接口表示的是"like-a"关系
  • 接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能改变其值
  • 抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值

引用:
Java 8 explained: Default Methods
Java 8新特性探究(二)深入解析默认方法

你可能感兴趣的:(Java8 接口的默认方法)