专栏首页汤圆学JavaJava8中的默认方法
原创

Java8中的默认方法

作者:汤圆

个人博客:javalover.cc

前言

大家好啊,我是汤圆,今天给大家带来的是《Java8中的默认方法》,希望对大家有帮助,谢谢

文章纯属原创,个人总结难免有差错,如果有,麻烦在评论区回复或后台私信,谢啦

简介

在Java之前,我们接触到的接口,都是只定义方法,不实现方法

(你看下面这几个人,像不像接口)

但是到了Java8就不一样了,因为在接口中新增了默认方法

这样的话,有些活,就可以交给接口自己去做了,而不用实现类去做(Java你这是在收买人心啊)

我们下面以问答的形式来介绍默认方法的相关知识点(据说问答模式可以让人更好地记忆?)

目录

  • 什么是默认方法?
  • 为啥要提供默认实现?
  • 那我如果不提供呢?
  • 这个功能主要是针对谁?
  • 实现了默认方法的接口和抽象类有区别吗?
  • 是不是可以说实现了多重继承?

正文

什么是默认方法

默认方法是接口中用default修饰的方法,其中包含方法内容

比如下面这个:

public interface InterfaceDemo {
    // 普通方法,只定义,不实现
    void oldFun();
    // 默认方法,又定义,又实现
    default void newFun(){
        System.out.println("newFun");
    }
}

为啥要提供默认方法呢?

为了向后兼容(这也是导致Java变得臃肿的原因之一)。

因为升级系统时,难免会有一些新功能需要加入,此时如果接口类新增了方法,那么实现类就必须同步修改实现;

这样工作量还是很大的,而且很容易出错。

所以Java8开始,推出了接口的默认方法这个功能,使得接口升级变得更加平滑

比如下面的代码:InterfaceDemo就是上面那个接口

public class UserDemo implements InterfaceDemo{
    @Override
    public void oldFun() {
        System.out.println("oldFun");
    }
​
    public static void main(String[] args) {
        UserDemo demo = new UserDemo();
        /**
         *  InterfaceDemo升级后,新增了newFun方法
         *  但是由于newFun是默认方法,有提供实现内容
         *  所以这里的子类 UserDemo就可以直接使用
          */
        demo.newFun();
    }
}

我们可以看到,UserDemo没有实现新的方法newFun(),但是也可以编译运行,并直接调用newFun()

这就是默认方法的好处:对实现类来说是无痛升级的

如果不提供呢?

不提供的话,接口类升级时,系统有两个选择

  1. 实现类升级:
    • 实现类老老实实地按照接口升级后的方法,进行同步修改实现,但是工作量大
  2. 实现类不升级:
    • 实现类不升级也是可以的,只要不引入接口类的新版本就可以了,那么这个时候系统还是可以运行的,这没啥问题。但是谁能保证一辈子都不更新系统呢?如果更新系统时,接口类库升级到新版本,那么编译还是通不过

主要针对谁?

接口的默认方法主要是针对类库设计者

实现了默认方法的接口和抽象类有区别吗

区别没有之前那么多,但还是有的:

  1. 抽象类单继承,接口类多实现
  2. 抽象类中的属性定义时不需要初始化,接口类的属性定义时要初始化(默认修饰符为public static final)

是不是可以说Java现在也实现了多重继承?

可以这么说。

但是现在面临的一个新问题,就是多重继承带来的二义性问题,有点类似之前介绍的致命方块(也叫菱形问题)

如下面的UML图所示

比如上面这种,你无法知道A会调用哪个接口的fun方法

所以编译器会报错:

com.jalon.java8.defaultmethod.A inherits unrelated defaults for fun() from types com.jalon.java8.defaultmethod.B and com.jalon.java8.defaultmethod.C

解决办法:

  • 先覆写fun方法
  • 再显示声明调用哪个接口的fun方法

代码如下:

​
public class A implements B,C{
​
    @Override
    public void fun(){
        // 显示调用B的默认方法
        B.super.fun();
    }
​
    public static void main(String[] args) {
        A a = new A();
        // 这里会打印B的fun
        a.fun();
    }
}
interface D{
    default void fun(){
        System.out.println("D");
    }
}
interface B extends D{
    @Override
    default void fun(){
        System.out.println("B");
    }
}
interface C extends D{
    @Override
    default void fun(){
        System.out.println("C");
    }
}

总结

  • 什么是默认方法:接口中用default修饰且包含方法内容的方法
  • 为什么要提供默认方法:向后兼容,使系统平滑过渡;主要针对类库设计者
  • 多重继承带来的问题:二义性,也叫菱形问题;解决办法就是子类尽量覆写默认方法并显式声明调用哪个方法(实际上这个问题很少出现,因为它属于编译错误,写代码时随时可以发现)

后记

最后,感谢大家的观看,谢谢

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java8 默认方法

    默认方法就是接口可以有实现方法,而且不需要实现类来实现其方法。相对于JDK1.8之前的接口来说,新增了可以接口中实现方法。

    烟草的香味
  • Java8 默认方法 default method

    在 java 8 之前,接口与其实现类之间的 耦合度 太高了(tightly coupled),当需要为一个接口添加方法时,所有的实现类都必须随之修改。默认方法...

    一觉睡到小时候
  • Java8 接口的静态方法和默认方法

    java8的接口中可以有default方法及static方法。 普通的抽象方法不可以有实现,实现此接口的类必须实现所有抽象方法。 默认方法必须有实现,实现此...

    呼延十
  • Java8新特性:默认方法详解

    Java8 中的默认方法是针对接口添加的新特性,它是指接口可以直接对方法进行实现,实现方式很简单,直接在方法定义处添加 default 关键字即可,如下所示。

    南风
  • 【小家java】java8中接口方法引发的思考(默认方法、static静态方法)

    java8可以说是jdk版本的一次重大升级,给我们也带来了非常多的新特性,而本文就针对于java8中很重要的新特性之一:接口方法。来讨论一下平时使用中可能遇到的...

    YourBatman
  • Java8新特性第2章(接口默认方法)

    在Java中一个接口一旦发布就已经被定型,除非我们能够一次性的更新所有该接口的实现,否者在接口的添加新方法将会破坏现有接口的实现。默认方法就是为了解决这一问题的...

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

    作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了...

    冰河
  • laravel-admin select框默认选中的方法

    laravel-admin后台框架的select选择框的默认选中,结合select2的js插件;

    砸漏
  • laravel中数据显示方法(默认值和下拉option默认选中)

    开发中,我们存储一个下拉列表的值一般采用数字代存储,而我们在页面显示的时候需要显示他的真实值

    砸漏
  • Java中的默认接口方法和静态接口方法

    在接口中使用关键字default声明并提供具体实现,而且该方法不需要添加public关键字就可以公开调用,甚至你可以在其实现类中覆写(@Override)。

    码农小胖哥
  • C# 8.0 的默认接口方法

    突然,我想对所有的人类添加一个新的特性,例如,添加一个自我介绍的方法,所以我在IPerson里添加了Introduce()这个方法:

    solenovex
  • java抽象方法,静态方法,默认方法

    在了解抽象方法和默认方法之前需要先了解什么是接口 接口是功能的集合,是一种数据类型 接口里定义方法默认是public abstract(抽象方法),没有具体...

    许喜朝
  • Linux中修改mysql默认编码的方法步骤

    在开发过程中,如果还原MySQL数据库后,数据库数据出现乱码,可以通过修改数据库默认编码来解决。

    砸漏
  • nginx 关闭默认站点的方法

    当别人把垃圾域名转向至你的服务器时, 如果不采取措施,那么后果不堪设想。 国内机房一般都要求网站主关闭空主机头,防止未备案的域名指向过来造成麻烦。 Ng...

    习惯说一说
  • pycharm 解除默认unittest模式的方法

    点击如图所示的工具图标,Tools-python integrated Tools-Default test runner 设置为Nosetests或者py.t...

    砸漏
  • 【答疑解惑】Java中的默认构造器和equals方法

    有一些网友在学习Java基础知识是遇到一些问题小编来解答一下。 1、Java中的默认构造器: 在Java中你要创建一个对象肯定会调用new语句来创建一个对象,在...

    程序员互动联盟
  • Java中Interface的方法和常量的默认访问修饰符

    Java中Interface常量的默认访问修饰符为:public static final 

    wuweixiang
  • 细品Java8中hashCode方法

    散列函数(英语:Hash function)又称散列算法、哈希函数,是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量...

    居士
  • Java 8 基础教程 - 默认方法

    正如其名,在Java 8中,默认方法就是使用default关键字标记的定义在接口中的方法。如果子类不重写这些方法,那么在子类调用这些方法的时候会直接调用接口中的...

    代码拾遗

扫码关注云+社区

领取腾讯云代金券