资讯专栏INFORMATION COLUMN

Java 8 新特性之默认方法(Default Methods)

QLQ / 3002人阅读

摘要:概述引入了新的语言特性默认方法。覆写默认方法,这跟类与类之间的覆写规则相类似。静态默认方法的另一个特性是接口可以声明并且可以提供实现静态方法本文首发于凌风博客新特性之默认方法作者凌风

1. 概述

Java 8 引入了新的语言特性——默认方法(Default Methods)。

默认方法允许您添加新的功能到现有库的接口中,并能确保与采用旧版本接口编写的代码的二进制兼容性。

1.1 为什么要有默认方法

在 Java 8之前,接口与其实现类之间的耦合度太高了,当需要为一个接口添加方法时,所有的实现类都必须随之修改。默认方法解决了这个问题,它可以为接口添加新的方法,而不会破坏已有的接口的实现。这在 lambda 表达式作为 Java 8 语言的重要特性而出现之际,为升级旧接口且保持向后兼容提供了途径。

还有就就是 Java 8 的函数式接口只允许有一个抽象方法,但可以有多个默认方法。

String[] array = new String[] {"hello",", ","world", };
List list = Arrays.asList(array);
list.forEach(System.out::println); // 这是 jdk 1.8 新增的接口默认方法

这个 forEach 方法是 jdk 1.8 新增的接口默认方法,正是因为有了默认方法的引入,才不会因为 Iterable 接口中添加了 forEach 方法就需要修改所有 Iterable 接口的实现类。

1.2 语法格式
interface InterfaceA {
    default void print() {
        System.out.println("InterfaceA print");
    }
}
2. 默认方法(default) 2.1 实例
interface InterfaceA {
    default void print() {
        System.out.println("InterfaceA print");
    }
}

class ClassA implements InterfaceA {

}
public class Java8Test {
    public static void main(String[] args) {
        new ClassA().print(); // 打印:“InterfaceA print”
    }
}

ClassA 类并没有实现 InterfaceA 接口中的 print 方法,InterfaceA 接口中提供了 print 方法的默认实现,因此可以直接调用 ClassA 类的 print 方法。

2.2 默认方法的继承
interface InterfaceA {
    default void print() {
        System.out.println("InterfaceA print");
    }
}

interface InterfaceB extends InterfaceA {

}

interface InterfaceC extends InterfaceA {
    @Override
    default void print() {
        System.out.println("InterfaceC print");
    }
}

interface InterfaceD extends InterfaceA {
    @Override
    void print();
}
public class Java8Test {
    public static void main(String[] args) {
        new InterfaceB() {}.print(); // 打印:"InterfaceA print"
        new InterfaceC() {}.print();// 打印:"InterfaceC print"
        new InterfaceD() {
            @Override
            public void print(){
                System.out.println("InterfaceD print");
            }
        }.print();// 打印:“InterfaceD print”

        // 或者使用 lambda 表达式
        ((InterfaceD) () -> System.out.println("InterfaceD print")).print();
    }
}

接口默认方法的继承分三种情况(分别对应上面的 InterfaceB 接口、InterfaceC 接口和 InterfaceD 接口):

不覆写默认方法,直接从父接口中获取方法的默认实现。

覆写默认方法,这跟类与类之间的覆写规则相类似。

覆写默认方法并将它重新声明为抽象方法,这样新接口的子类必须再次覆写并实现这个抽象方法。

2.3 类优先原则

接口默认方法的类优先原则

若一个接口中定义了一个默认方法,而另外一个父类或接口中又定义了一个同名的方法时

选择父类中的方法。如果一个父类提供了具体的实现,那么接口中具有相同名称和参数的默认方法会被忽略。

接口冲突。如果一个父接口提供一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认方法),那么必须覆盖该方法来解决冲突

public interface FunA {
    default String getName() {
        return "aaaa";
    }
}
public class ClassA {
    public String getName() {
        return "bbb";
    }
}
public class SubClass extends ClassA implements FunA {
}

测试方法

@Test
public void t1(){
    SubClass subClass = new SubClass();
    System.out.println(subClass.getName()); // 输出的是 bbb
}

注意 :

default 关键字只能在接口中使用(以及用在 switch 语句的 default 分支),不能用在抽象类中。

接口默认方法不能覆写 Object 类的 equalshashCodetoString 方法。

接口中的静态方法必须是 public 的,public 修饰符可以省略,static 修饰符不能省略。

即使使用了 java 8 的环境,一些 IDE 仍然可能在一些代码的实时编译提示时出现异常的提示(例如无法发现 java 8 的语法错误),因此不要过度依赖 IDE。

3. 静态默认方法

Java 8 的另一个特性是接口可以声明(并且可以提供实现)静态方法

interface InterfaceA {
    default void print() {
        System.out.println("InterfaceA print");
    }

    static void staticMethod(){
        System.out.println("InterfaceA staticMethod");
    }
}
本文首发于凌风博客:Java 8 新特性之默认方法(Default Methods)
作者:凌风

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72780.html

相关文章

  • JAVA9-12特性简述

    摘要:本文是个人在企业内部分享使用的简要大纲,列举了的重要更新,文章的结构较简单,也不规范,鉴于近期写若干文章时总会忘记一些新特性所处的版本,特将此大纲流留用。 本文是个人在企业内部分享使用的简要大纲,列举了JAVA9-12的重要更新,文章的结构较简单,也不规范,鉴于近期写若干文章时总会忘记一些新特性所处的版本,特将此大纲流copy留用。 一 JAVA9 新特性 1.Java Platfo...

    TigerChain 评论0 收藏0
  • Java基础知识整理注解

    摘要:注解提供了一种安全的类似注释的机制,用来将任何的信息或元数据与程序元素类方法成员变量等进行关联。为程序的元素类方法成员变量加上更直观更明了的说明,这些说明与程序的业务逻辑无关,并且提供给指定的工具或框架使用。 什么是注解? Annotation 是 Java5 之后开始引入的新特性,中文为注解。注解提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(...

    blastz 评论0 收藏0
  • Java8特性学习笔记

    摘要:虽然目前工作环境仍然以为主,不过目前已是大势所趋了。标准函数式接口新的包定义旨在使用的广泛函数式接口。这一改进使得拥有了类似于多继承的能力。 从Java8发布到现在有好几年了,而Java9也提上发布日程了(没记错的话好像就是这个月2017年7月,也许会再度跳票吧,不过没关系,稳定大于一切,稳定了再发布也行),现在才开始去真正学习,说来也是惭愧。虽然目前工作环境仍然以Java6为主,不过...

    wthee 评论0 收藏0
  • Java Lambda 表达式(又名闭包 (Closure)/ 匿名函数 ) 笔记

    摘要:表达式又名闭包匿名函数笔记根据终于在中引入了表达式。函数式接口要介绍中表达式的实现,需要知道什么是函数式接口。但同样需要保证外部的自由变量不能在表达式中被改变。 Java Lambda 表达式(又名闭包 (Closure)/ 匿名函数 ) 笔记 根据 JSR 335, Java 终于在 Java 8 中引入了 Lambda 表达式。也称之为闭包或者匿名函数。 showImg(https...

    fou7 评论0 收藏0
  • Java8 特性:Lambda表达式和虚拟扩展方法标注

    摘要:摘要添加了表达式闭包和特性支持,包括方法的引用,增强类型推断,和虚拟扩展方法。围绕的语言功能支持包括虚拟扩展方法,这将使接口的源代码和二进制兼容的方式演变升级。 Author:Joseph D. Darcy Organization:Oracle Owner:Brian Goetz Created:2011/11/1 Updated:2013/2/21 Type:Feature Sta...

    UsherChen 评论0 收藏0

发表评论

0条评论

QLQ

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<