摘要: 从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. selenium webdriver处理HTML5 的视频播放

    import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; import org.openqa.sele ...

  2. PIMPL(二)

    文档下载 上一篇文档,PIMPL(一) 1 如何使用PIMPL 有多种方式实现PIMPL,这里按照<Effective C++>中介绍的方式. 1.1 基本步骤 假设原有Person如下: ...

  3. cocos代码研究(2)Layer学习笔记

    auto layer = Layer::create(); /*************华丽分割线*************/ auto layer = LayerColor::create(Colo ...

  4. js判断两个日期是否严格相差整年(合同日期常用)

    1.var beginDate = new Date($("#InvoiceStartTime").val()); var endDate = new Date($("# ...

  5. hexo修改Next主题的样式

    Next主题默认对超链接只有下划线样式,很容易被忽略,就想着怎么修改下 主题样式是在\hexoBlog\themes\next\source\css,这里面保存了Muse,Mist和Pisces三个主 ...

  6. owl.carousel

    简介 Owl Carousel 是一个强大.实用但小巧的 jQuery 幻灯片插件,它具有一下特点: 兼容所有浏览器 支持响应式 支持 CSS3 过度 支持触摸事件 支持 JSON 及自定义 JSON ...

  7. webp格式

    有时候你右键保存了一张图片,然后好气啊,打不开.这要么是webp格式,要么,,,,要么有问题啊. WebP格式,谷歌大法开发的一种旨在加快图片加载速度的图片格式.图片压缩体积大约只有JPEG的2/3, ...

  8. MySQL从删库到跑路_高级(五)——触发器

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.触发器简介 1.触发器简介 触发器是和表关联的特殊的存储过程,可以再插入,删除或修改表中的数据时触发执行,比数据 ...

  9. python webdriver 显示等待判断元素是可以被点击的,但是执行脚本时,却提示元素不能点击的解决办法?

    我之前运行没问题的环境是firefox版本50,对应的驱动是没有问题的,现在firefox自动升级到了60,驱动没有变,我试着把浏览器装回了50,再试就好了, 所以应该是浏览器跟驱动geckodriv ...

  10. Python中文件的读写操作的几种方法

    对文件的操作,步骤为:打开一个文件-->读取/写入内容-->保存文件 文件读写的3中模式 # 1.w 写模式,它是不能读的,如果用w模式打开一个已经存在的文件,会清空以前的文件内容,重新写 ...