1. 程式人生 > >一文帶你認識Java8中介面的預設方法

一文帶你認識Java8中介面的預設方法

Java8是Oracle於2014年3月釋出的一個重要版本,其API在現存的介面上引入了非常多的新方法。

例如,Java8的List介面新增了sort方法。在Java8之前,則每個實現了List介面的類必須定義sort方法的實現,或者從父類中繼承它的實現。想象一下,如果List介面的繼承體系非常龐雜,那麼整個集合框架的維護量有多麼大!

為此,在Java8中引入了一種新的機制:介面支援申明帶實現的方法。

預設方法

前文提到了Java8中List介面新增了sort方法,其原始碼如下:

public interface List<E> extends Collection<E> {
    
    // ...其他成員
        
    default void sort(Comparator<? super E> c) {
      ...
      ...
    }
}

可以看到,這個新增的sort方法有方法體,由default修飾符修飾,這就是介面的預設方法。

很顯然,預設方法不是static的,所以必須由介面的實現類的例項來呼叫這些預設方法。

下面自定義一個介面,練習使用預設方法。

public interface Sized {
    // 普通抽象方法,預設是public abstract修飾的,沒有方法體
    int size();

    /*
     * 預設方法,有方法體
     * 任何一個實現了Sized介面的類都會向動繼承isEmpty的實現
     */
    default boolean isEmpty() {
        return this.size() == 0;
    }
}

其實,隨著JDK版本的不斷升級,API在不斷演進,預設方法在Java8的API中已經大量地使用了,上面List介面中的sort方法就是其中一個。

和抽象類的區別

有同學可能發現了,Java8中加入了預設方法的介面,這不就是以前的抽象類嗎?其實,兩者還是有區別的。

  • 一個類只能繼承一個抽象類;但是一個類可以實現多個介面。
  • 抽象類有例項變數,而介面只能有類變數

解決衝突

我們知道Java語言中一個類只能繼承一個父類,但是一個類可以實現多個介面。隨著預設方法在Java8中的引入,有可能出現一個類繼承了多個簽名一樣的方法。這種情況下,類會選擇使用哪一個函式呢?

為解決這種多繼承關係,Java8提供了下面三條規則:

  1. 類中的方法優先順序最高,類或父類中宣告的方法的優先順序高於任何宣告為預設方法的優先順序。
  2. 如果第一條無法判斷,那麼子介面的優先順序更高:方法簽名相同時,優先選擇擁有最具體實現的預設方法的介面, 即如果B繼承了A,那麼B就比A更加具體。
  3. 最後,如果還是無法判斷,繼承了多個介面的類必須通過顯式覆蓋和呼叫期望的方法, 顯式地選擇使用哪一個預設方法的實現。

讓我們一起看幾個例子 。

場景1:
public interface A {
    default void hello() {
        System.out.println("hello from A");
    }
}
public interface B extends A {
    default void hello() {
        System.out.println("hello from B");
    }
}
public class C implements A, B {
    public static void main(String[] args) {
        new C().hello();
    }
}


如圖1,是這個場景的UML圖。

我們對照上面三條規則來看,類C中main()方法會輸出什麼?

  1. 規則(1))不滿足。
  2. 因為B繼承了A,所以B比A更具體,所以應該選擇B的hello()方法。所以,程式會列印輸出"hello from B"。
場景2:

如果C像下面這樣繼承了D,會怎麼樣?

public class D implements A {

}
public class C extends D implements A, B {
    public static void main(String[] args) {
        new C().hello();
    }
}


如圖2,是這個場景的UML圖。

同樣,我們對照著三條規則來看:

  1. C雖然繼承了D,但D中未覆蓋A的預設方法。
  2. 接著,編譯器會在A和B中做選擇,由於B更具體,所以,程式會列印輸出"hello from B"。
場景3:

將上面的D稍作修改:

public class D implements A {
    public void hello() {
        System.out.println("hello from D");
    }
}

結果又如何?

由於依據規則(1),父類中宣告的方法具有更高的優先順序,所以程式會列印輸出"hello from D"。

場景4:

假設現在B不在繼承A:

public interface A {
    default void hello() {
        System.out.println("hello from A");
    }
}
public interface B {
    default void hello() {
        System.out.println("hello from B");
    }
}
public class C implements A, B {
    public static void main(String[] args) {
        new C().hello();
    }
}

如圖3,是這個場景的UML圖。

此時,由於編譯器無法識別A還是B的實現更加具體,所以會丟擲編譯錯誤:”C inherits unrelated defaults for hello() from types A and B“。

像這種場景要解決衝突,可以在C中覆蓋hello()方法並在方法內顯示的選擇呼叫A還是B的方法。

呼叫方式如下:

public class C extends D implements A, B {
    public void hello() {
        // 顯式地選擇呼叫介面B中的方法
        // 同理,要呼叫介面A中的方法,可以這樣:A.super.hello()
        B.super.hello();
    }

    public static void main(String[] args) {
        // 輸出 hello from B
        new C().hello();
    }
}
場景5:
public interface A {
    default void hello() {
        System.out.println("hello from A");
    }
}
public interface B extends A{

}
public interface C extends A{

}
public class D implements B, C {
    public void hello() {
        new D().hello();
    }
}

此時,只有一個方法申明可以選擇,所以程式會輸出"hello from A"。

END

相關推薦

認識Java8中介面的預設方法

Java8是Oracle於2014年3月釋出的一個重要版本,其API在現存的介面上引入了非常多的新方法。 例如,Java8的List介面新增了sort方法。在Java8之前,則每個實現了List介面的類必須定義sort方法的實現,或者從父類中繼承它的實現。想象一下,如果List介面的繼承體系非常龐雜,那麼整個

理解JavaLock的實現原理

當多個執行緒需要訪問某個公共資源的時候,我們知道需要通過加鎖來保證資源的訪問不會出問題。java提供了兩種方式來加鎖,一種是關鍵字:synchronized,一種是concurrent包下的lock鎖。synchronized是java底層支援的,而concurrent包

認識Java泛型基礎

Java泛型基礎 認識泛型 泛型是在JDK1.5之後增加的新功能. 泛型可以解決資料的安全性問題, 主要的原理是在類宣告的時候通過一個標識表示類中某個屬性的型別或者是某個方法的返回值及引數型別. 格式: 訪問許可權 class 類名稱<泛型, …

實現遊戲的音樂、音效設定

在遊戲開發過程中,背景音樂和音效的設定總是繞不過的,今天就來帶大家實現一個簡單的背景音樂和音效的設定邏輯。   1.首先將音樂資源和圖片資源都匯入到工程中(公眾號後臺回覆「AudioTest」可獲得完整工程,圖片和音樂資源來自關東昇老師《Cocos2d-x實戰》,侵刪。):  

瞭解Spring核心介面Ordered的實現及應用

### 前言 最近在看框架的時候,發現了這個介面,在此進行總結,希望能夠給大家幫助,同時提升自己。 ### order介面的大體介紹 Spring框架中有這個一個介面,名字叫Ordered,聯想我們在資料庫中應用的Ordered,很容易想到它的含義就是用來排序。那麼問題來了,Spring中為什麼要定義這樣一個

認識Docker

Docker是一個容器技術的應用,而底層是由於Linux容器實現的,Docker只是實現層。 一、Linux容器 1、隔離與共享 一臺伺服器執行著多個邏輯隔離的伺服器程序,誰的執行環境都不希望影響到誰,也就是一個物理機需要虛擬出多個環境或容器,Linux提供一種建立和進入容器的方式,作業系統讓應用程式就像在獨

從夏農熵到手推KL散度:縱覽機器學習的資訊理論

資訊理論與資訊熵是 AI 或機器學習中非常重要的概念,我們經常需要使用它的關鍵思想來描述概率分佈

什麼,這些人還不認識?!有姿勢地侃深度學習大佬

大資料文摘作品編譯:餘志文,笪潔瓊,錢天培近幾年間,深度學習的興起造就了一批超級巨星。一向在學術

分鐘認識深度學習的知識蒸餾

摘要:知識蒸餾(knowledge distillation)是模型壓縮的一種常用的方法 一、知識蒸餾入門 1.1 概念介紹 知識蒸餾(knowledge distillation)是模型壓縮的一種常用的方法,不同於模型壓縮中的剪枝和量化,知識蒸餾是通過構建一個輕量化的小模型,利用效能更好的大模型的監督資訊,

深度解析騰訊雲直播答題方案

exc com erp 同學 col 測試 的確 影響 cep 歡迎大家前往雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 作者:騰訊視頻雲 進入2018年最火的新鮮事物無疑就是“直播答題”了,動輒上百萬的獎金更是吸引了大量用戶的參與。一場直播動輒幾百萬的獎金,每人可以分到

了解激光雷達重要指標及參數

因此 一個 https 速度 .com p s 展示 jpg left 博客轉載自:https://www.leiphone.com/news/201801/oySuWNzftbNrWwpv.html 雷鋒網(公眾號:雷鋒網)按:本文作者SLAMTEC(思嵐科技公號slam

吃透執行緒池

微信公眾號:[Amos部落格] 內容目錄 TreadPoolexecutor原始碼解析 類關係圖 Executor介面 ExecutorService介面 AbstractExecutorService 成員變數

快速瞭解最火的數字經濟(大資料、人工智慧等都有)

人工智慧行業應用加速(暴富機會由“網際網路+”轉向AI+) “網際網路+”紅利已開發將盡,未來,新的暴富紅利將由“人工智慧”接棒。從產業演進看,科技巨頭正加速全球化併購,打造AI生態閉環,開源化也將成為全球性趨勢。開源化使得人工智慧的行業運用門檻急遽降低,未來幾年將迎來人工智慧行業應用浪潮。 2

某高校計算機程式設計教授教如何快速入門python,進入程式設計

如何快速入門Python 學習任何一門語言都是從入門(1年左右),通過不間斷練習達到熟練水準(3到5年),少數人最終能精通語言,成為執牛耳者,他們是金字塔的最頂層。雖然萬事開頭難,但好的開始是成功的一半,今天這篇文章就來談談如何開始入門 Python。只要方向對了,就不怕路遠。 設定目標

學會使用YOLO及Opencv完成影象及視訊流目標檢測(上)|附原始碼

計算機視覺領域中,目標檢測一直是工業應用上比較熱門且成熟的應用領域,比如人臉識別、行人檢測等,國內的曠視科技、商湯科技等公司在該領域佔據行業領先地位。相對於影象分類任務而言,目標檢測會更加複雜一些,不僅需要知道這是哪一類影象,而且要知道影象中所包含的內容有什麼及其在影象中的位置,因此,其工業應用比較廣泛。那麼

學會使用YOLO及Opencv完成圖像及視頻流目標檢測(上)|附源碼

目錄 aliyun sele 分數 connected 出了 man 領域 turn 計算機視覺領域中,目標檢測一直是工業應用上比較熱門且成熟的應用領域,比如人臉識別、行人檢測等,國內的曠視科技、商湯科技等公司在該領域占據行業領先地位。相對於圖像分類任務而言,目標檢測會更加

瞭解求職面試那些名詞(乾貨)

喬兄剛剛經歷了19秋招,收穫了百度offer,馬上要迎來了19春招,有很多公眾號的粉絲經常會問今年不是2018年嗎,你咋就已經完成了2018校招了?由於被很多人經常問起,下面喬兄給大家普及一下跟校招相關的名詞。 現在時間是北京時間 2018.11.15,請務必根據現在的時間去推測你的情況。 201

還沒寫過爬蟲的小白點進來,入門python爬蟲(小白福利)

入門 準備工作 需要準備的東西: Python、scrapy、一個IDE或者隨便什麼文字編輯工具。 隨便建一個工作目錄,然後用命令列建立一個工程,工程名為miao,可以替換為你喜歡的名字。 scrapy startproject miao 隨後你會得到如下的一個由scrapy建立

瞭解 Raft 一致性協議的關鍵點

此文已由作者孫建良授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。 Raft 協議的釋出,對分散式行業是一大福音,雖然在核心協議上基本都是師繼 Paxos 祖師爺(lamport) 的精髓,基於多數派的協議。但是 Raft 一致性協議的貢獻在於,定義了可易於實現的一致性協議

看懂卷積神經網路(CNN)讓意想不到的10創新idea

    全文摘要 卷積神經網路(CNN)可以說是深度學習發展的一個縮影,特別是現在在計算機視覺方面已經得到了非常成熟的應用,在目標檢測、目標追蹤等方面也是獨領風騷,本文將講述卷積神經網路近些年來的發展歷程,以及它到底創新在什麼地方。本文略長,看完大約3