Java8接口中引入default关键字的本质原因详析

目录
  • 接口的常规实现方式
  • 接口中的default
  • 接口中的static
  • Default好处
  • 总结

接口的常规实现方式

熟悉java接口的同学都知道,接口被某些类实现后,一旦在接口中增加了新方法,那么实现该接口的所有类都要实现这个新增的方法(即使这个新增的接口对某些类没有用处)。

定义一个接口

public interface IDemo {
    void func1();
}

类CDemo1实现接口IDemo

public class CDemo1 implements IDemo{
    @Override
    public void func1() {
    }
}

类CDemo2实现接口IDemo

public class CDemo2 implements IDemo{
    @Override
    public void func1() {
    }
}

在IDemo中新增加方法func2()

public interface IDemo {
    void func1();
    void func2();
}

可以看到CDemo1和CDemo2中需要强制实现方法func2(),如下图所示:

接口中的default

上面的实例导致了前面提出的那个问题,一旦在接口中增加了新方法,那么已经实现了该接口的所有的类都要实现这个新增的方法!那么,如果是JDK中的某个核心接口需要变更,需要新增某些方法呢?这个工作量更是可想而知,我们来看一下java.util.Collection这个接口,它在jdk1.7中的方法包括:

而在JDk 1.8中 Collection接口中包括方法如下:

其中新增的接口,都用default来修饰(jdk1.7升级到jdk1.8后,接口的重要变化),源代码如下:

default Stream<E> stream() {
 return StreamSupport.stream(spliterator(), false);
}

default Stream<E> parallelStream() {
    return StreamSupport.stream(spliterator(), true);
}

default Spliterator<E> spliterator() {
    return Spliterators.spliterator(this, 0);
}

default boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);
    boolean removed = false;
    final Iterator<E> each = iterator();
    while (each.hasNext()) {
        if (filter.test(each.next())) {
            each.remove();
            removed = true;
        }
    }
    return removed;
}

我们不仅大吃一惊,这还是我们熟知的接口吗?接口中的方法居然有了实现代码!吃惊过后,我们来想想作者的意图。还是上面的代码,我们新增方法func3(),并完成简单的实现

public interface IDemo {
    void func1();
    void func2();
    default void func3(){
        System.out.println("this is default func2");
    }
}

然后查看类CDemo1,一切正常,没有任何错误提示:

实例化CDemo1后,可以正常调用func3方法,代码如下:

public static void main(String[] args) {
    CDemo1 cd1=new CDemo1();
    cd1.func3();
}

读到这里发现接口中通过default关键字来进行接口实现的好处了吧,简单四个字就是 “方便扩展” !通过这个技术可以做到在接口中新增加方法并且不会影响到已经实现了该接口的所有的类!包括jdk1.8新引入的Lambda表达式也是基于这一知识点来实现的!

接口中的static

与此同时,从jdk1.8开始,接口中可以通过static关键字来修饰方法,同样可以对方法进行实现

static  void func4(){
    System.out.println("this is static func4");
}

调用方法也非常的简单,接口.static 方法,例如:

IDemo.func4();

大家可以这样理解,接口中的static方法可以作为工具方法来提供给大家进行方便调用!

Default好处

原先接口的缺陷是,修改接口后,则需要修改全部实现该接口的类,所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。

总结

到此这篇关于Java8接口中引入default关键字本质原因的文章就介绍到这了,更多相关Java8接口引入default关键字内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们

(0)

相关推荐

  • Java8的default和static关键字的使用讲解

    1. default和static关键字 a.default 用在接口中, 为该接口的实现类的方法.  --> 不能通过接口直接调用. static 也是用在接口中, 同Class中的static方法一样, 是类级别的方法, 而不是对象的方法.  --> 可以通过接口直接调用. b.一个接口可以有多个default方法, 也可以有多个static方法. 2. default 在使用中的注意事项 如下面的例子 有两个接口, InterA和InterB, 都有一个方法, 为defaultFunct

  • Java8接口中引入default关键字的本质原因详析

    目录 接口的常规实现方式 接口中的default 接口中的static Default好处 总结 接口的常规实现方式 熟悉java接口的同学都知道,接口被某些类实现后,一旦在接口中增加了新方法,那么实现该接口的所有类都要实现这个新增的方法(即使这个新增的接口对某些类没有用处). 定义一个接口 public interface IDemo { void func1(); } 类CDemo1实现接口IDemo public class CDemo1 implements IDemo{ @Overri

  • 用Vue-cli搭建的项目中引入css报错的原因分析

    我最近在研究Vue的路上,今天遇到了个问题,在vue cli 引入css报错,后来查询了很多资料,那么今天也算个学习笔记吧! 1.问题描述 之前用vue-cli搭建的项目,在main.js中引入elementUI库中的css,或者在其他文件中(比如App.vue)引入自己的css文件(假如你的文件是在src目录下),都会报一个相同的错.下如图 经过一番折腾之后发现需要在build文件下的webpack.base.conf.js中加上下面的代码即可 { test: /\.css$/, includ

  • TypeScript中import type与import的区别详析

    目录 背景 import type vs import 使用 import type 的好处 参考链接 总结 背景 这周遇到了一个比较奇怪的问题:如何在 TypeScript 中根据某个 enum 的取值来执行后续逻辑? 按理来说应该很简单,这是 enum 的定义: export enum MyEnum { DEFAULT = 0, SOME_VALUE = 1, SOME_OTHER_VALUE = 2, } 然后在另一个项目中,通过 import type 来引入: import type

  • C++中4种强制类型转换的区别详析

    前言 C++即支持C风格的类型转换,又有自己风格的类型转换.C风格的转换格式很简单,但是有不少缺点的: 1.转换太过随意,可以在任意类型之间转换.你可以把一个指向const对象的指针转换成指向非const对象的指针,把一个指向基类对象的指针转换成一个派生类对象的指针,这些转换之间的差距是非常巨大的,但是传统的C语言风格的类型转换没有区分这些. 2.C风格的转换没有统一的关键字和标示符.对于大型系统,做代码排查时容易遗漏和忽略. C++风格完美的解决了上面两个问题.1.对类型转换做了细分,提供了四

  • Vue3.0中Ref与Reactive的区别示例详析

    目录 Ref与Reactive Ref Reactive Ref与Reactive的区别 shallowRef 与shallowReactive toRaw ---只修改数据不渲染页面 markRaw --- 不追踪数据 toRef --- 跟数据源关联 不修改UI toRefs ---设置多个toRef属性值 customRef ---自定义一个ref ref 捆绑页面的标签 总结 Ref与Reactive Ref Ref 用来创建基础类型的响应式数据,模板默认调用value显示数据.方法中修

  • Javascript中click与blur事件的顺序详析

    一.现象 最近在开发中碰到了一个需求,具体需求如下图. 这是一个很常见的需求,input框负责在点击回车和失焦的时候确认输入.button负责清除输入,input绑定代码为: input.addEventListener('blur',function(){ console.log('input blur'); }); input.addEventListener('keyup',function(){ console.log('input keyup'); }); "X"绑定的代码为

  • Linux中改变文件权限的chmod命令详析

    前言 Linux的chmod命令是用来改变文件权限的,对于文件或者目录的普通权限,共有 3 种,分别为: r:读取: w:写入: x:执行. 今天为大家详细介绍下chmod命令的意义和用法 chmod命令 改变文件权限 一.符号模式 命令格式: chmod [who] operator [permission] filename who包含的选项及其含义: u 文件属主权限. g 属组用户权限. o 其他用户权限. a 所有用户(文件属主.属组用户及其他用户). operator包含的选项及其含

  • python中时间转换datetime和pd.to_datetime详析

    前言 我们在python对数据进行操作时,经常会选取某一时间段的数据进行分析.这里为大家介绍两个我经常用到的用来选取某一时间段数据的函数:datetime( )和pd.to_datetime( ). (一)datetime( ) (1)获取指定的时间和日期.datetime(%Y,%m,%d,%H,%M,%S) datetime共有6个参数,分别代表的是年月日时分秒.其中年月日是必须要传入的参数,时分秒可以不传入,默认全为零. eg: (2)将Str和Unicode转化为datetimedate

  • Laravel中为什么不使用blpop取队列详析

    前言 Redis 的 list 数据结构常用来做消息队列,通常使用的命令有 lpop/rpop ,还有带阻塞版的 blpop/brpop 等.Laravel 5.3 消息队列也是用的 lpop 取消息,为什么不用阻塞版的 blpop 呢? blpop 不用一直轮询,还可以同时取多个队列,blpop high low 30,更方便实现队列的优先级. 安全队列和不安全队列 什么是不安全的队列?比如客户端 lpop(统一以 lpop 为例) 从 redis 取出来的 job(任务)还没处理完进程挂掉了

  • java中for循环执行的顺序图文详析

    for循环基础 for循环是最灵活也是最常用的循环结构,表达式一般如下: for(条件表达式1:条件表达式2:条件表达式3){ 语句块: } 接下来详细介绍Java for循环执行顺序的相关内容,先看看一道面试题, 来自小米笔试 static boolean foo(charc) { System.out.print(c); return true; } public static void main(String[] args) { int i =0; for(foo('B');foo('A'

随机推荐