在JDK1.8以前,接口(interface)没有提供任何具体的实现,在《JAVA编程思想》中是这样描述的:“interface这个关键字产生了一个完全抽象的类,它根本就没有提供任何具体的实现。它允许创建者确定方法名、参数列表和返回类型,但是没有任何方法体。接口只提供了形式,而未提供任何具体实现”。

  但是这一限制在JDK1.8中被打破了,JDK1.8开始,接口允许定义默认方法和静态方法。

  接口默认方法的语法很简单,即:

  1. default关键字 methodName(参数列表) { // 实现体 }

  接口静态方法语法与类的静态方法类似,不同的是接口静态方法的修饰符只能是public。

1、默认方法

  为了提高代码的可重用性。接口的默认方法有助于在扩展系统功能的同时,不对现有的继承关系及类库产生很大的影响。例如在JDK1.8中,Java集合框架的Collection接口增加了stream()等默认方法,这些默认方法即增强了集合的功能,又能保证对低版本的JDK的兼容。

  举个简单的例子,假如有一个Animal接口其中有fly()和swim()方法,有一个鸟类Bird和一个鱼类Fish同时实现这个接口,代码如下:

  Animal接口:

  1. public interface Animal {
  2. void run();
  3. void swim();
  4. }

  Bird.java

  1. public class Bird implements Animal {
  2.  
  3. @Override
  4. public void swim() {
  5. // do nothing
  6. }
  7.  
  8. @Override
  9. public void fly() {
  10. System.out.println("birds can fly...");
  11. }
  12. }

  Fish.java

  1. public class Fish implements Animal {
  2.  
  3. @Override
  4. public void swim() {
  5. System.out.println("fish can swim......");
  6. }
  7.  
  8. @Override
  9. public void fly() {
  10. // donothing
  11. }
  12. }

  从上代码可以看到,因为Animal中定义了fly()和swim()方法,所以所有实现它的类都要覆写这两个方法,在Bird类中,鸟会飞,不会游泳,但是又必须要实现swim()方法,Fish类不会飞,但是又必须要实现fly()方法。代码出现冗余。

  假如现在又有了新的需求,需要在Animal接口中再增加一个cry()方法,那么之前所有实现了Animal接口的方法势必都在再覆写cry()方法,整个系统中可能会有很多地方需要同步修改,而此时,default方法和静态方法就显得尤为必要了。

  改写上面的例子:

  Animal.java

  1. public interface Animal {
  2. default void fly() {
  3. System.out.println("birds can fly...");
  4. }
  5.  
  6. default void swim() {
  7. System.out.println("fishes can swim......");
  8. }
  9. }

  Bird.java

  1. public class Bird implements Animal {
  2. }

  Fish.java

  1. public class Fish implements Animal {
  2. }

  测试类:

  1. public class TestMain {
  2.  
  3. public static void main(String[] args) {
  4.  
  5. Bird bird = new Bird();
  6. bird.fly();
  7.  
  8. Fish fish = new Fishe();
  9. fish.swim();
  10. }
  11. }

  运行结果:

  1. birds can fly...
  2. fishes can swim......

  从修改后代码可以看出,代码得到了复用,Animal实现类中也没有了冗余。

2、静态方法

  假如有一个Animal工厂接口,该接口中有一个静态方法create()专门生产不同的Animal,在JDK1.8后由于引入了Lambda表达式,使子类不用覆写该接口的create()方法也可以生产任意的Animal,代码如下:

  1. public interface AnimalFactory {
  2.  
  3. static Animal create(Supplier<Animal> supplier) {
  4. return supplier.get();
  5. }
  6. }

  测试类:

  1. public class TestAnimalFactory {
  2.  
  3. public static void main(String[] args) {
  4.  
  5. // 生产一只鸟
  6. Animal bird = AnimalFactory.create(Bird::new);
  7. bird.fly();
  8.      // 生产一条鱼
  9. Animal fish = AnimalFactory.create(Fishe::new);
  10. fish.swim();
  11. }
  12. }

  运行结果:

  1. birds can fly...
  2. fishes can swim......

3、接口静态方法的“类优先”原则

  如果一个接口实现类提供了具体的实现,那么接口中具有相同名称和参数的默认方法会被忽略,如改写之前的Bird类:

  1. public class Bird implements Animal {
  2.  
  3. public void fly() {
  4. System.out.println("Bird类中的fly方法:birds can fly...");
  5. }
  6. }

  测试类:

  1. public class TestMain {
  2.  
  3. public static void main(String[] args) {
  4.  
  5. Bird bird = new Bird();
  6. bird.fly();
  7. }
  8. }

  运行结果:

  1. Bird类中的fly方法:birds can fly...

  可见,调用的是Bird类中自己的fly()方法而不是Animal接口中的默认方法。

4、接口冲突

  假如一个类实现了两个接口,两个接口中都有同样的默认方法,哪个是有效的?

  答案是:两个都无效!

  该类必须要覆该方法来解决冲突,否则编译器将会报错。

  

  

Java8新特性之四:接口默认方法和静态方法的更多相关文章

  1. JDK8新特性之接口默认方法与静态方法

    接口默认方法与静态方法 有这样一些场景,如果一个接口要添加一个方法,那所有的接口实现类都要去实现,而某些实现类根本就不需要实现这个方法也要写一个空实现,所以接口默认方法就是为了解决这个问题. 接口静态 ...

  2. 乐字节-Java8核心特性实战-接口默认方法

    JAVA8已经发布很久,是自java5(2004年发布)之后Oracle发布的最重要的一个版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性,对于国内外互联网公司来说,Java8是以后技术 ...

  3. 【Java8新特性】接口中的默认方法和静态方法,你都掌握了吗?

    写在前面 在Java8之前的版本中,接口中只能声明常量和抽象方法,接口的实现类中必须实现接口中所有的抽象方法.而在Java8中,接口中可以声明默认方法和静态方法,本文,我们就一起探讨下接口中的默认方法 ...

  4. 【Java8新特性】- 接口中默认方法修饰为普通方法

    Java8新特性 - 接口中默认方法修饰为普通方法 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学 ...

  5. Java8新特性_接口中的默认方法

    默认方法由来猜想 1. Collection接口.Collections公共类.  同是操作集合,为啥要搞俩?没必要.在接口中搞一些默认实现,一个接口即搞定了. 2. Java8支持Lambda表达式 ...

  6. java8新特性:接口的默认方法与静态方法

    接口中一共可以定义三种方法: 1.抽象方法,也就是需要实现者必须实现的方法,最常见的那种 2.默认方法,不需要实现者实现 3.静态方法,不需要实现者实现 默认方法: 允许在已有的接口中添加新方法,而同 ...

  7. Java8 新特性 函数式接口

    什么是函数式接口   函数式接口是Java8引用的一个新特性,是一种特殊的接口:SAM类型的接口(Single Abstract Method).但是它还是一个接口,只是有些特殊罢了.  函数式接口的 ...

  8. Java8 新特性----函数式接口,以及和Lambda表达式的关系

    这里来讲解一下Java8 新特性中的函数式接口, 以及和Lambda 表达式的关系.看到过很多不少介绍Java8特性的文章,都会介绍到函数式接口和lambda表达式,但是都是分别介绍,没有将两者的关系 ...

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

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

随机推荐

  1. python 中的csv读写

    1.首先 import csv 2.读一个csv文件 data = open(filename) lines = csv.reader(data)  #reader 函数和 dirtreader函数的 ...

  2. windows + maven + eclipse

    一处教程:http://www.yiibai.com/maven/maven_overview.html     Maven中央仓库信息速查:http://maven.outofmemory.cn/ ...

  3. node.js,express入门看详细篇

    先最简单的代码 安装 npm install express app.js 代码内容 const express = require('express') const app = express() ...

  4. MySQL技术内幕 InnoDB存储引擎(笔记)

    1. InnoDB 体系架构 其中,后台程序主要负责刷新内存池中的数据,保证缓冲池中的内存缓存的是最近的数据. 此外将已经修改的数据刷新到磁盘文件,同时保证在数据库发生异常的时候Innodb能恢复正常 ...

  5. win10装ubuntu双系统

    由于在win下进行web开发出现各种问题相当头疼. 所以今天折腾了一天想装个ubuntu,查看了网上好多教程,不得不说,网上的人很多都是不负责任的,教程都是过时根本就不负责任,关键的地方一笔带过,简单 ...

  6. 记一次webpack打包优化

    未进行打包优化的痛点: 随着项目的不断扩大,引入的第三方库会越来越多,我们每次build的时候会对所有的文件进行打包,耗时必定很长,不利于日常开发. 解决思路: 第三方库我们只是引入到项目里来,一般不 ...

  7. Centos6.5DRBD加载失败,系统更换yum源(国内163)

    我安装的系统是centos6.5的,要在系统上安装DRBD镜像软件,安装完后,无法加载modprobe drbd. 需要更新kernel. 1,首先,先把yum源更换成国内的,不然无法更新kernel ...

  8. Proxy是在什么时候调用InvocationHandler的invoke方法的

    最近看到spring的动态代理,扒到深处看到时 Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);看到这一句,顿时比较懵逼,还是 ...

  9. asp.net mvc 使用 Autocomplete 实现类似百度,谷歌动态搜索条提示框。

    Autocomplete是一个Jquery的控件,用法比较简单. 大家先看下效果: 当文本框中输入内容,自动检索数据库给出下拉框进行提示功能. 需要用此控件大家先到它的官方网站进行下载最新版本: ht ...

  10. 深入理解SpringBoot之装配条件

    我们知道自动装配是SpringBoot微服务化的核心,它会把META-INF/spring.factoires里配置的EnableAutoConfiguration注册到IOC容器里.但是,请大家考虑 ...