default关键字的用法

目录

  • 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();
    }
}

此时,接口-类关系图,如下:

结果如下:

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...

翻译过来就是,名为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");
    }
}

此时,接口-类关系图,如下:

方法一结果如下:

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();
    }
}

此时,接口-类关系图,如下:

结果如下:

Here is MyImpl1

总结

default的使用场景:

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

? ①直接调用父接口实现

? ②继承多个接口

? ③类优先于接口

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

善于学习,善于总结

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

原文地址:https://www.cnblogs.com/chudonghai/p/11588268.html

时间: 2024-08-01 08:10:20

default关键字的用法的相关文章

default关键字用法

概述:今天在梳理了java基础知识的时候,发现default(默认)关键字有两个作用,分别如下: 1.在switch语句的时候使用default 例如: 2.定义接口的时候用default来修饰方法 default是在java8中引入的关键字,也可称为Virtual ,他的出现是为了解决实现接口的缺陷问题(就是如果想修改接口时,所有实现了该接口的类都需要去修改),例如: 以上的代码的实现,我相信大家已经理解default关键字的作用,那么下面我在拓展一些信息 a)如何同时继承了两个接口,而两个接

C++11模板句柄的实现:委派构造函数、default关键字分析

C++11,使用委派构造函数,并且快速初始化变量,default关键字重声明默认构造函数,回复pod状态.分析与推荐用法. 目前为止,VS2012和2013对异常声明的兼容还是停留在代码沟通的级别,没有进行编译类型检查,出现如下错误可忽略. warning C4290: 忽略 C++ 异常规范,但指示函数不是 __declspec(nothrow) 下为:VS2012不支持委托构造函数,建议使用cocos2d-x 3.2及版本的朋友更新VS至2013版. 1>d:\cpp_lab\testque

C++中的默认函数与default和delete用法

时间:2014.05.08 地点:基地 -------------------------------------------------------------------------------- 一.类中的默认函数 a.类中默认的成员函数 1.默认构造函数 2.默认析构函数 3.拷贝构造函数 4.拷贝赋值函数 5.移动构造函数 6.移动拷贝函数 b.类中自定义的操作符函数 1.operator 2.operator& 3.operator&& 4.operator* 5.op

super关键字的用法

package com.frank;//定义包名,必须是第一行.如果没有包名,那么就会被放在一个没有名字的默认包中. import java.util.*; /** 继承 */ public class Sample {     public static void main(String[] args)     {         OldMan o = new OldMan("张三",80);         System.out.println("名字:"+o.

.Net 基础new关键字的用法

一.new的基本功能 一般说来,new关键字在.net中用于以下四个场合. 作为运算符,用于创建对象和调用构造函数,范围用得最多吧. 实现多态. 作为修饰符,用于向基类成员隐藏继承类成员,一般继承情况下,扩展基类方法用得多. 作为泛型参数约束,用于在泛型声明中约束用作类型参数的参数类型,这个也好像用得多吧. 二.new的基本用法 先来说说作为泛型参数约束的用法. MSDN 中的定义是:new约束指定泛型类声明中的任何类型参数都必须有公共的无参构造函数.当泛型类型创建类型的新实例时,将此约束应用于

yield关键字的用法

在上一篇文章中,说了下foreach的用法,但是还是比较复杂的,要实现接口才能进行遍历,有没有简单些的方法呢?答案是肯定的.且看下面. yield关键字的用法: 1.为当前类型添加一个任意方法,但是要求该方法的返回值类型必须是IEnumerable:<代码1-1> 1 class Person 2 { 3 public string Name { get; set; } 4 public int Age { get; set; } 5 6 public string[] _Name = new

Java基础-synchronized关键字的用法(转载)

原文地址:http://blog.csdn.net/cq361106306/article/details/38736551 synchronized--同步 顾名思义是用于同步互斥的作用的. 这里精简的记一下它的使用方法以及意义: 当synchronized修饰?this或者非静态方法或者是一个实例的时候,所同步的锁是加在this或者实例对象引用上面的.比如a,b同为Main类的实例化对象,a调用被同步的方法,和b调用被同步的方法,没有形成互斥.但是不同线程的a对象调用被同步的方法就被互斥了.

c#多线程中Lock()关键字的用法小结

本篇文章主要是对c#多线程中Lock()关键字的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待. 每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数.这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生.

mysql 去除重复 Select中DISTINCT关键字的用法

在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的所有值.其原因是 distinct只能返回它的目标字段,而无法返回其它字段,这个问题让我困扰了很久,用distinct不能解决的话,我只有用二重循环查询来解决,而 这样对于一个数据量非常大的站来说,无疑是会直接影响到效率的.所以我花了很多时间来研究这个问题,网上也查不到解决方案,期间把容容拉来帮忙,