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就是用來修飾這個方法的。

​ ①直接調用父接口實現

​ ②繼承多個接口

​ ③類優先於接口

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

善於學習,善於總結

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM