java8之默认方法

作者: 野狗道人闯红灯 | 来源:发表于2018-05-19 10:09 被阅读1次

默认方法是啥

默认方法是由default修饰符修饰,并像类中声明的其他方法一样包含方法体。是Java8中新添加的能力。

默认方法能干啥

可选方法

默认方法的主要应用场景在定义API上,可以避免临时往接口里面加方法导致的尴尬。

举一个身边的例子。比如Android升级的时候往接口里加了个方法,但是方法又不常用,升级的时候我们就不得不实现一下这个方法然后加一个空实现或者抛出一个未支持异常。但是现在有了默认方法,这种场景下Android就可以写一个默认方法,不用我们非得实现一个我们不会去使用的接口方法了。

总之,对于那些不是一定要实现的接口方法,我们可以避免在实现的时候刻意留白的情况出现。

函数式接口

之前讲过,函数式接口是只包含一个抽象方法的接口。这句话在以前不需要过多考虑,但是现在有了默认方法就不一样了。因为默认方法不是抽象方法,所以我们多些几个默认方法是不影响的。实际上现在的函数式接口Predicate、Function以及Comparator确实也引入了默认方法。

行为的多继承

当年学Java的时候,学到继承的位置需要特别注意的一点是Java不像C++一样支持行为多继承。现在不一样了,有了默认方法大家可以在接口里写实现了,这时实现多个接口我们自然就拥有它们各个接口的能力了。

利用这一点,我们可以把能够解决独立能力的通用代码抽成接口,并把需要的能力用默认方法实现。当我们想要用的这些能力的时候实现一下接口就可以了。这种方式与模版设计模式类似。

默认方法存在啥问题

方法名冲突

在默认方法之前如果实现两个有重名的方法的接口,对于重名的接口方法实现成一个就好了。但是现在有了默认方法,如果两个接口中有同名的默认方法,那么在同时实现这两个接口的时候会选择使用哪一个方法呢?这种情况有极低可能会出现,但还是要有规则来处理这种问题。

解决问题的三条规则

  1. 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。
  2. 如果无法依据第一条进行判断,那么子接口的优先级最高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。
  3. 最后,如果还是无法判断,继承了多个接口的类必须通过显示覆盖和调用期望的方法,显示的选择使用哪一个默认方法的实现。

以上三条规则就能够处理所有冲突的问题,下面举个例子说明一下。

示例一
public interface A {
    default void hello() {
        System.out.println("A");
    };
}

public interface B extends A{
    @Override
    default void hello() {
        System.out.println("B");
    };
}

public class D implements A {
    //未实现hello()
}

public class C extends D implements B, A {
    public static void main(String... args) {
        new C().hello();
    }
}

看上面代码,首先根据规则1,类中声明的方法具有最高权限,但是类D中并未实现默认方法hello。这里如果类D实现了hello,那么他就拥有最高优先级了。接下来看规则2,看谁更加具体,因为B继承了A,那么B更加具体,所以打印出来的是"B"。

示例二

先上代码

public interface A {
    default void hello() {
        System.out.println("A");
    };
}

public interface B {
    default void hello() {
        System.out.println("B");
    };
}
public class C implements B, A {
    public static void main(String... args) {
        new C().hello();
    }
}

这种情况会打印什么呢?答案是会抛出编译错误,因为无法判断出谁更具体一些。这个时候就需要显式调用了。

具体的方法是覆盖实现该方法,并且在方法中显式调用。关于显示调用,Java8中引入的新语法X.super.m(...),其中X是你希望调用的m方法所在的父接口。例如,上面的问题就可以像下面代码这样显示调用。

public class C implements B,A {

    public static void main(String... args) {
        new C().hello();
    }
    
    @Override
    public void hello() {
        A.super.hello();
    }
}

最后

多说两句

虽然现在接口里也可以写实现了,抽象类和接口还是有区别的。首先类只能继承一个抽象类,但可以实现多个接口。其次抽象类可以定义变量,接口不行。

个人认为默认函数最大的意义还是便于API的编写,避免接口必须实现的痛苦。

最最后

打完,收工!不要问我为什么跳过了Stream,因为功能很强大,写起来太费劲了。欢迎大家讨论提出意见~~

欢迎关注【Funny新青年】微信公众号

相关文章

  • Java 8 之默认方法和静态接口方法

    转载自30分钟入门Java8之默认方法和静态接口方法 默认方法 默认方法让我们能给我们的软件库的接口增加新的方法,...

  • java8接口中的默认方法

    java8接口中的默认方法 概述默认方法 java8中可以在接口中定义一个default修饰的方法,例如: 这样任...

  • 30分钟入门Java8之方法引用

    30分钟入门Java8之方法引用 前言 之前两篇文章分别介绍了Java8的lambda表达式和默认方法和静态接口方...

  • java8 新特性总结

    java8新特性 1.接口方法默认实现:java8中接口方法可以有默认实现,需要加入default关键字。 2.L...

  • java8之默认方法

    默认方法是啥 默认方法是由default修饰符修饰,并像类中声明的其他方法一样包含方法体。是Java8中新添加的能...

  • Java8学习笔记目录

    Java8学习笔记 -- 接口的默认方法与静态方法 Java8学习笔记 -- Lambda表达式,Function...

  • Java8_教程_01

    JAVA8 教程 默认方法 使用:只需要实现抽象方法,默认方法可以被直接调用 Lambda expressions...

  • 接口(interface)和抽象类(abstract class

    1、接口中的方法默认都是 public,所有方法在接口中不能有默认实现(Java8 开始接口方法可以有默认实现),...

  • 接口(interface)和抽象类(abstract class

    接口中的方法默认都是 public,所有方法在接口中不能有默认实现(Java8 开始接口方法可以有默认实现),而抽...

  • 默认方法

    什么是默认方法 java8引入了一个新的功能,叫默认方法,通过默认方法你可以指定接口方法的默认实现。换句话说:就是...

网友评论

    本文标题:java8之默认方法

    本文链接:https://www.haomeiwen.com/subject/vdsodftx.html