摘要: 从java8开始,接口不只是一个只能声明方法的地方,我们还可以在声明方法时,给方法一个默认的实现,我们称之为默认接口方法,这样所有实现该接口的子类都可以持有该方法的默认实现。

  · 待定

  一. 引入默认接口方法的背景

  java8可以看做是java版本更新迭代过程中变化最大的一个版本(与时俱进,方能不灭,我们应该感到欣慰),但是经过这么多年的发展和迭代,java的源码俨然已是一个庞然大物,要在这样庞大的体积上大动干戈,肯定不易。所以当第一次看到java8的默认接口方法的时候,我第一感觉就是这是java的设计人员在填自己之前挖的坑。

  从前几篇的讲解中我们知道java8在现有的接口上添加了许多方法,比如List的sort(Comparator? super E c)方法。如果按照java8之前接口的设计思路,当给一个接口添加方法声明的时候,实现该接口的类都必须为该新添加的方法添加相应的实现。考虑兼容性,这样是不可取的,所以说这是一个坑,而新的特性又要求不得不为接口添加一些新的方法,为了兼得鱼和熊掌,java8的设计人员提出了默认接口方法的概念。

  这样说来,默认接口方法似乎是为api的设计人员而开发的,离我们普通开发人员还有些距离,这样想有点图森破啦,虽然我们不用去设计jdk,但是我们在日常的开发过程中还是会有提供api给别的业务方调用的需求,当我们在更新我们api的时候,就可以采用默认方法来提供更加高级的功能,同时保持兼容性。

  二. 默认接口方法的定义

  默认接口方法的定义很简单,只要在接口的方法定义前添加一个default关键字即可,如下:

  publicinterfaceA{/**

  *默认方法定义

  */

  defaultvoidmethod(){

  System.out.println(Thisisadefaultmethod!);

  }

  }

  当我们这样定义一个默认方法之后,所有实现该接口的子类都间接持有了该方法。或者你会和我一样觉得接口和抽象类越来越像了,确实,不过它们之间还是有如下差别:

  1.一个类只能继承一个类,但是可以实现多个接口2.抽象类可以定义变量,而接口却不能

  抽象除了解决了我们上面提及到的问题,还具有如下好处:

  1.对于一些不是每个子类都需要的方法,我们给它一个默认实现,从而避免我们在子类中对其无意义的实现(一般我们都会thrownewUnsupportedException())2.默认方法为java的多重继承提供了新的途径(虽然我们只能继承一个类,但是我们可以实现多个接口啊,现在接口也可以定义默认方法了)

  三. 冲突及其解决方法

  因为一个类可以实现多个接口,所以当一个类实现了多个接口,而这些接口中存在两个或两个以上方法签名相同的默认方法时就会产生冲突,java8定义如下三条原则来解决冲突:

  1.类或父类中显式声明的方法,其优先级高于所有的默认方法2.如果1规则失效,则选择与当前类距离最近的具有具体实现的默认方法3.如果2规则也失效,则需要显式指定接口

  下面通过几个例子加以说明:

  例1

  publicinterfaceA{/**

  *默认方法定义

  */

  defaultvoidmethod(){

  System.out.println(A'sdefaultmethod!);

  }

  }publicinterfaceBextendsA{/**

  *默认方法定义

  */

  defaultvoidmethod(){

  System.out.println(B'sdefaultmethod!);

  }

  }publicclassCimplementsA,B{publicstaticvoidmain(String[]args){newC().method();

  }

  }//输出:B'sdefaultmethod!

  此处因为接口B相对于A距离C更近,同时B的method是一个具体的默认实现,依据规则2,所以此处实际上调用的是接口B的默认方法

  例2

  publicclassDimplementsA{

  }publicclassCextendsDimplementsA,B{publicstaticvoidmain(String[]args){newC().method();

  }

  }//输出:B'sdefaultmethod!

  例2在原有接口A、B的基础上,添加了一个实现接口A的类D,然后类C继承于D,并实现A和B,此处虽然C离D更近,但因为D的具体实现在A中,所以B中的默认方法还是距离最近的默认实现,依据规则2,此处实际上调用的是B的默认方法。

  例3

  //A接口不变publicinterfaceB{/**

  *默认方法定义

  */

  defaultvoidmethod(){

  System.out.println(B'sdefaultmethod!);

  }

  }publicclassCimplementsA,B{@Override

  publicvoidmethod(){//必须显式指定

  B.super.method();

  }publicstaticvoidmain(String[]args){newC().method();

  }

  }

  例3中接口B不再继承自接口A,所以此时C中调用默认方法method()距离接口A和B的具体实现距离相同,编译器无法确定,所以报错,此时需要显式指定:B.super.method()。

Java8 新特性之默认接口方法的更多相关文章

  1. Java8新特性系列-默认方法

    Java8 Interface Default and Static Methods 原文连接:Java8新特性系列-默认方法 – 微爱博客 在 Java 8 之前,接口只能有公共抽象方法. 如果不强 ...

  2. 乐字节-Java8新特性之函数式接口

    上一篇小乐带大家学过 Java8新特性-Lambda表达式,那什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的.从Java8开始引入了函数式接口,其说明比较简单:函数式接口 ...

  3. Java8新特性之二:方法引用

    上一节介绍了Java8新特性中的Lambda表达式,本小节继续讲解Java8的新特性之二:方法引用.方法引用其实也离不开Lambda表达式. 1.方法引用的使用场景 我们用Lambda表达式来实现匿名 ...

  4. Java8新特性:Function接口和Lambda表达式参考

    Lambda基本:https://blog.csdn.net/wargon/article/details/80656575 https://www.cnblogs.com/hyyq/p/742566 ...

  5. Java8新特性之四:接口默认方法和静态方法

    在JDK1.8以前,接口(interface)没有提供任何具体的实现,在<JAVA编程思想>中是这样描述的:"interface这个关键字产生了一个完全抽象的类,它根本就没有提供 ...

  6. Java8新特性Optional、接口中的默认方法与静态方法

    Optional Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念 ...

  7. Java8新特性之函数式接口

    <Java 8 实战>学习笔记系列 定义 函数式接口只定义一个抽象方法,可以有多个默认方法 函数式接口的接口名上,会被@FunctionalInterface标注 作用 函数式接口的方法可 ...

  8. 乐字节-Java8新特性-接口默认方法

    总概 JAVA8 已经发布很久,而且毫无疑问,java8是自java5(2004年发布)之后的最重要的版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性. Java8 新特性列表如下: 接 ...

  9. java8新特性学习:函数式接口

    本文概要 什么是函数式接口? 如何定义函数式接口? 常用的函数式接口 函数式接口语法注意事项 总结 1. 什么是函数式接口? 函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口 ...

随机推荐

  1. unity3d-小案例之角色简单漫游

    准备资源 我这里从网上下载一个角色模型,里面有一组动画.有站立.奔跑.杀怪等 我们来实现角色的前后左后移动,即键盘上的WSDA键,这里因为没有行走的动画.索性就用奔跑代替了!! 暂时先不计较代码冗余的 ...

  2. Lintcode: Hash Function && Summary: Modular Multiplication, Addition, Power && Summary: 长整形long

    In data structure Hash, hash function is used to convert a string(or any other type) into an integer ...

  3. Linux系统——JumpServer跳板机的搭建和部署

    公网源部署jumpserver跳板机 建立阿里云公网源yum仓库(服务端)[root@localhost ~]# lsanaconda-ks.cfg install.log.syslog jumpse ...

  4. Servlet—基础

    什么是Servlet? 1 . jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代 码,Web容器将JSP的代码编译成JVM能够识别 ...

  5. C++矩阵库 Eigen 快速入门

    最近需要用 C++ 做一些数值计算,之前一直采用Matlab 混合编程的方式处理矩阵运算,非常麻烦,直到发现了 Eigen 库,简直相见恨晚,好用哭了. Eigen 是一个基于C++模板的线性代数库, ...

  6. Linux基础命令---fsck

    fsck 检查或者修复指定的文件系统,可以是设备名.挂载点,还可以是一个ext2的label,或者是一个UUID.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.ope ...

  7. AtCoder Beginner Contest 086 D - Checker

    Time limit : 2sec / Memory limit : 256MB Score : 500 points Problem Statement AtCoDeer is thinking o ...

  8. Centos文件切割利器_split命令及cat命令合并文件

    有个文件要处理,因为很大,所以想把它切成若干份,每份N行,以便并行处理.split命令可以将一个大文件分割成很多个小文件,有时需要将文件分割成更小的片段,为提高可读性,生成日志等 命令格式 -b:值为 ...

  9. P2322 [HNOI2006]最短母串问题

    P2322 [HNOI2006]最短母串问题 AC自动机+bfs 题目要求:在AC自动机建的Trie图上找到一条最短链,包含所有带结尾标记的点 因为n<12,所以我们可以用二进制保存状态:某个带 ...

  10. 20145310 Exp7 网络欺诈技术防范

    实验后回答问题 (1)通常在什么场景下容易受到DNS spoof攻击 局域网内最容易遭受攻击.通过DNS欺骗就可以轻松地将网址转到钓鱼网站.而我们平时最常用的局域网应该就是公共热点吧,特别是有的地方的 ...