Java8新特性之四:介面預設方法和靜態方法

来源:https://www.cnblogs.com/wuhenzhidu/archive/2019/04/22/10753328.html
-Advertisement-
Play Games

在JDK1.8以前,介面(interface)沒有提供任何具體的實現,在《JAVA編程思想》中是這樣描述的:“interface這個關鍵字產生了一個完全抽象的類,它根本就沒有提供任何具體的實現。它允許創建者確定方法名、參數列表和返回類型,但是沒有任何方法體。介面只提供了形式,而未提供任何具體實現”。 ...


  在JDK1.8以前,介面(interface)沒有提供任何具體的實現,在《JAVA編程思想》中是這樣描述的:“interface這個關鍵字產生了一個完全抽象的類,它根本就沒有提供任何具體的實現。它允許創建者確定方法名、參數列表和返回類型,但是沒有任何方法體。介面只提供了形式,而未提供任何具體實現”。

  但是這一限制在JDK1.8中被打破了,JDK1.8開始,介面允許定義預設方法和靜態方法。

  介面預設方法的語法很簡單,即:

default關鍵字 methodName(參數列表) { // 實現體 }

  介面靜態方法語法與類的靜態方法類似,不同的是介面靜態方法的修飾符只能是public。

1、預設方法

  為了提高代碼的可重用性。介面的預設方法有助於在擴展系統功能的同時,不對現有的繼承關係及類庫產生很大的影響。例如在JDK1.8中,Java集合框架的Collection介面增加了stream()等預設方法,這些預設方法即增強了集合的功能,又能保證對低版本的JDK的相容。

  舉個簡單的例子,假如有一個Animal介面其中有fly()和swim()方法,有一個鳥類Bird和一個魚類Fish同時實現這個介面,代碼如下:

  Animal介面:

1 public interface Animal {
2     void run();
3     void swim();
4 }

  Bird.java

public class Bird implements Animal {

    @Override
    public void swim() {
        // do nothing
    }

    @Override
    public void fly() {
        System.out.println("birds can fly...");
    }
}

  Fish.java

 1 public class Fish implements Animal {
 2 
 3     @Override
 4     public void swim() {
 5         System.out.println("fish can swim......");
 6     }
 7 
 8     @Override
 9     public void fly() {
10         // donothing
11     }
12 }

  從上代碼可以看到,因為Animal中定義了fly()和swim()方法,所以所有實現它的類都要覆寫這兩個方法,在Bird類中,鳥會飛,不會游泳,但是又必須要實現swim()方法,Fish類不會飛,但是又必須要實現fly()方法。代碼出現冗餘。

  假如現在又有了新的需求,需要在Animal介面中再增加一個cry()方法,那麼之前所有實現了Animal介面的方法勢必都在再覆寫cry()方法,整個系統中可能會有很多地方需要同步修改,而此時,default方法和靜態方法就顯得尤為必要了。

  改寫上面的例子:

  Animal.java

1 public interface Animal {
2     default void fly() {
3         System.out.println("birds can fly...");
4     }
5 
6     default void swim() {
7         System.out.println("fishes can swim......");
8     }
9 }

  Bird.java

1 public class Bird implements Animal {
2 }

  Fish.java

1 public class Fish implements Animal {
2 }

  測試類:

 1 public class TestMain {
 2 
 3     public static void main(String[] args) {
 4 
 5         Bird bird = new Bird();
 6         bird.fly();
 7 
 8         Fish fish = new Fishe();
 9         fish.swim();
10     }
11 }

  運行結果:

birds can fly...
fishes can swim......

  從修改後代碼可以看出,代碼得到了復用,Animal實現類中也沒有了冗餘。

2、靜態方法

  假如有一個Animal工廠介面,該介面中有一個靜態方法create()專門生產不同的Animal,在JDK1.8後由於引入了Lambda表達式,使子類不用覆寫該介面的create()方法也可以生產任意的Animal,代碼如下:

1 public interface AnimalFactory {
2 
3     static Animal create(Supplier<Animal> supplier) {
4         return supplier.get();
5     }
6 }

  測試類:

 1 public class TestAnimalFactory {
 2 
 3     public static void main(String[] args) {
 4 
 5         // 生產一隻鳥
 6         Animal bird = AnimalFactory.create(Bird::new);
 7         bird.fly();
 8      // 生產一條魚
 9         Animal fish = AnimalFactory.create(Fishe::new);
10         fish.swim();
11     }
12 }

  運行結果:

birds can fly...
fishes can swim......

3、介面靜態方法的“類優先”原則

  如果一個介面實現類提供了具體的實現,那麼介面中具有相同名稱和參數的預設方法會被忽略,如改寫之前的Bird類:

1 public class Bird implements Animal {
2 
3     public void fly() {
4         System.out.println("Bird類中的fly方法:birds can fly...");
5     }
6 }

  測試類:

1 public class TestMain {
2 
3     public static void main(String[] args) {
4 
5         Bird bird = new Bird();
6         bird.fly();
7     }
8 }

  運行結果:

Bird類中的fly方法:birds can fly...

  可見,調用的是Bird類中自己的fly()方法而不是Animal介面中的預設方法。

4、介面衝突

  假如一個類實現了兩個介面,兩個介面中都有同樣的預設方法,哪個是有效的?

  答案是:兩個都無效!

  該類必須要覆該方法來解決衝突,否則編譯器將會報錯。

  

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.cd 到指定目錄 2.運行命令 python 3之前 python 3+ 3.運行後: 4.在瀏覽器輸入 http://localhost:8888/. 測試,然後就可以瀏覽網頁 ...
  • 閱讀目錄 一、模塊和包 模塊(module)的概念: 在電腦程式的開發過程中,隨著程式代碼越寫越多,在一個文件里代碼會越來越長,越來越不容易維護。 為了編寫可維護的代碼,我們把很多函數分組,分別放到不同的文件里,這樣,每個文件包含的代碼就相對較少,很多編程語言都採用這種組織代碼的方式。在Pytho ...
  • 新聞 "Ionide試驗版本" "FSharp路線圖介紹" "Blazor官方預覽" ".NET Framework 4.8發佈" ".NET Core 3 Preview 4發佈" "需要來自FSharp.Data.SqlClient用戶的反饋" "Fable.React 5發佈" "Though ...
  • 一、介面思想 建立關聯的橋梁,方便管理代碼 介面思想提現:為類拓展功能 介面類:用來定義功能的類,為繼承它的子類提供功能的。 該類的功能方法一般不需要有實現體,實現體有繼承它的子類自己去實現。 介面類:用來定義功能的類,為繼承它的子類提供功能的。 該類的功能方法一般不需要有實現體,實現體有繼承它的子 ...
  • volatile是java虛擬機提供的輕量級的同步機制 JMM(Java記憶體模型)是圍繞著併發編程中原子性、可見性、有序性這三個特征來建立的 原子性:一個操作或多個操作要麼全部執行完成且執行過程不被中斷,要麼就不執行。 可見性:當多個線程同時訪問同一個變數時,一個線程修改了這個變數的值,其他線程能夠 ...
  • 包_繼承 1.包 包(package) 用於管理程式中的類,主要用於解決類的同名問題。包可以看成目錄。 包的作用: 【1】防止命名衝突 【2】允許類組成一個單元模塊,便於管理 【3】更好的保護類、屬性和方法 1.1定義包 package用於定義包,形如:package 路徑(包名) 必須寫到源文件的 ...
  • 1.包(package) 包(package) 用於管理程式中的類,主要用於解決類的同名問題。包也可以看成一個目錄。 包的作用 [1] 防止命名衝突。 [2] 允許類組成一個單元(模塊),便於管理和維護。 [3] 更好的保護類、屬性和方法 。 1.1 如何定義包 使用package進行定義,應放在源 ...
  • LinkedBlockingQueue的實現方式? LinkedBlockingQueue是有界的還是無界的隊列? LinkedBlockingQueue相比ArrayBlockingQueue有什麼改進? ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...