Java8特性之接口默认方法

是什么
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 : ABC
age : 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接口不再继承Father2,Son类同时实现Father1和Father2,你就会发现编译报错,其实就是相同的默认方法有两个,不知道用哪个,这个时候你就必须实现getName默认方法,如

public class Son implements Father1,Father2{

    @Override
    public String getName() {
        return Father1.super.getName();
    }
}

 


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值