default关键字的用法

default关键字的用法

前言

在学习集合时,深入到Iterable发现了这个default关键字

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

理论探究

default关键字在java中,目前有两个地方能用到

一是switch中的default:switch在匹配时,最后来一个default,防止因为没有匹配到结果,使后续程序异常。

二是接口中的default:从JDK8开始,接口中可以添加默认方法了,default就是用来修饰这个方法的。

代码实现

switch中的default

switch执行过程中,如果没有符合条件的case,就执行default下的代码块,这里的default并不是必要的,也可以不写,程序也会正常执行,只是,如果后续有业务用到这个switch的值,而代码中又没有匹配到相关结果,可能就会出问题。

package com.cdh.keyDefault;
/**
* @author chudonghai
* @ClassName SwitchDefaultDemo
* @Description switch中的default
*/

public class SwitchDefaultDemo {

    public static void main(String[] args) {
        defaultTest();
    }

    /*
     * 判断是否匹配:不匹配
     *       输出:ERROR!
     */
    private static void defaultTest() {
        String string = new String("helloworld");
        switch (string) {
        case "hello":
            System.out.println("hello case");
            break;
        case "world":
            System.out.println("world case");
            break;

        default:
            System.out.println("ERROR!");
            break;
        }
    }
}
接口中的default

重点来了,这是本篇的重头戏,这也是JDK8加入的新特性。

接口有很多的好处,诸如多实现,低耦合,对外提供规则等;

但缺点也会在某些场景中凸显出来,当修改接口时,需要修改全部实现该接口的类。

例如:JDK8,在Iterable中,新增了一个新方法forEach,这里就出现一个问题。

目前,JDK8之前的版本,集合框架都没有foreach方法,如何对已发布的接口进行修改而又不影响当前实现类的正常运行,这在生产中是一个很大的问题。对此,我们一般能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,无法同时满足既给接口添加新方法又不影响已有的实现,如果一味强行在每个类中进行添加,且不说风险问题,单是这个工作量就足以让程序员们彻夜不休,如果项目庞大,这个工作量更是让人生畏,所以,之前都是尽量避免这种改接口的问题。为此JDK8引入了默认方法default。它同时满足了既给接口添加新方法又不影响已有的实现这个大难题。

好了扯了这一堆希望你能听懂,不懂也没关系,咱看看代码:

接口中default的用法(代码实现)
1.直接调用父接口实现
/**
* @author chudonghai
* @InterfaceName Interface1
* @Description 创建接口Interface1,并在接口中定义默认方法helloworld
*/
public interface Interface1 {
    default void helloworld() {
        System.out.println("this is JDK8 Interface1");
    }
}
/**
* @author chudonghai
* @ClassName MyImpl1
* @Description MyImpl1:接口1的实现类,调用接口中的默认方法
*/
public class MyImpl1 implements Interface1{
    
    public static void main(String[] args) {
        MyImpl1 mi = new MyImpl1();
        mi.helloworld();
    }
}

此时,接口-类关系图,如下:
1754702-20190925231252826-1128809196.png
结果如下:

this is JDK8 Interface1
2.继承多个接口
/**
* @author chudonghai
* @ClassName Interface2
* @Description 创建接口Interface2,并在接口中定义默认方法helloworld
*/
public interface Interface2 {
    default void helloworld() {
        System.out.println("this is JDK8 Interface2");
    }
}
/**
* @author chudonghai
* @ClassName MyImpl1
* @Description MyImpl1:接口1,接口2的实现类,调用接口中的默认方法
*/
public class MyImpl1 implements Interface1,Interface2{
    
    public static void main(String[] args) {
        MyImpl1 mi = new MyImpl1();
        mi.helloworld();
    }
}

此时发现实现类MyImpl1会报错:Duplicate default methods named helloworld...
1754702-20190925231328898-1457195883.png
翻译过来就是,名为helloworld的默认方法重复啦,,,

也就是说,现在程序不知道你到底是要运行哪个接口中的helloworld方法,怎么办???

下面提供两种解决办法:

方法一:直接指定这个方法属于哪个接口。

方法二:直接进行重写此方法。

/**
* @author chudonghai
* @ClassName MyImpl1
* @Description MyImpl1:接口1,接口2的实现类,调用接口中的默认方法
*/
public class MyImpl1 implements Interface1,Interface2{
    
    public static void main(String[] args) {
        MyImpl1 mi = new MyImpl1();
        mi.helloworld();
    }

//  /**
//   * 方法一:直接指定这个方法属于哪个接口
//   * */
//  @Override
//  public void helloworld() {
//      Interface1.super.helloworld();
//  }
    
    /**
     * 方法二:直接重写此方法
     * */
    @Override
    public void helloworld() {
        System.out.println("Here is MyImpl1");
    }
}

此时,接口-类关系图,如下:
1754702-20190925231356230-614702491.png
方法一结果如下:

this is JDK8 Interface1

方法二结果如下:

Here is MyImpl1
3.类优先于接口
/**
* @author chudonghai
* @ClassName MyImpl2
* @Description MyImpl2继承MyImpl1(方法helloworld已重写)实现Interface2
*/
public class MyImpl2 extends MyImpl1 implements Interface2{
    
    /**
     * 此时,MyImpl2中调用的helloWorld到底是MyImpl1中的还是Interface2中的?
     * 答案:是MyImpl1中的
     * 原因:类优先于接口。从结果来看确是如此
     * */
    public static void main(String[] args) {
        MyImpl2 mi = new MyImpl2();
        mi.helloworld();
    }
}

此时,接口-类关系图,如下:
1754702-20190925231423374-77200939.png
结果如下:

Here is MyImpl1

总结

default的使用场景:

  1. switch中的default:switch在匹配时,最后添加default,防止因为没有匹配到结果,使后续程序异常。
  2. 接口中的default:从JDK8开始,接口中可以添加默认方法了,default就是用来修饰这个方法的。

​ ①直接调用父接口实现

​ ②继承多个接口

​ ③类优先于接口

=======================================================================================

善于学习,善于总结

=======================================================================================

转载于:https://www.cnblogs.com/chudonghai/p/11588268.html

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值