首頁 Java java教程 Java8的default方法詳細介紹

Java8的default方法詳細介紹

Jan 23, 2017 pm 03:15 PM

什麼是default方法?

Java 8發布以後,可以為介面新增方法,但是,介面仍然可以和它的實作類別保持相容。這非常重要,因為你開發的類別庫可能正在被多個開發者廣泛的使用。而Java 8之前,在類別庫中發布了一個介面以後,如果在介面中新增一個方法,那些實作了這個介面的應用使用新版本的介面就會有崩潰的危險。

有了Java 8,是不是就沒有這種危險了?答案是否定的。

為介面新增default方法可能會讓某些實作類別不可用。

首先,讓我們來看看default方法的細節。

在Java 8中,介面中的方法可以被實作(Java8中的static的方法也可以在介面中實現,但這是另一個主題)。介面中被實作的方法叫做default方法,用關鍵字default作為修飾符來識別。當一個類別實作一個介面的時候,它可以實作已經在介面中被實作過的方法,但這不是必須的。這個類別會繼承default方法。這就是為什麼當介面改變的時候,實作類別不需要做改動的原因。

多繼承的時候呢?

當一個類別實現了多於一個(例如兩個)接口,而這些接口又有同樣的default方法的時候,事情就變得很複雜了。類別繼承的是哪一個default方法呢?哪一個也不是!在這種情況下,類別要自己(直接或是繼承樹上更上層的類別)來實作default方法(才可以)。

當一個介面實作了default方法,另一個介面把default方法宣告成了abstract的時候,也是如此。 Java 8試圖避免不明確的東西,保持嚴謹。如果一個方法在多個介面中都有聲明,那麼,任何一個default實作都不會被繼承,你將會得到一個編譯時錯誤。

但是,如果你已經把你的類別編譯過了,那就不會出現編譯時錯誤了。在這一點上,Java 8是不一致的。它有它自己的原因,有於各種原因,在這裡我不想詳細的說明或者是深入的討論(因為:版本已經發布了,討論時間太長,這個平台從來沒有這樣的討論)。

1.假如你有兩個接口,一個實作類別。
2.其中一個介面實作了一個default方法m()。
3.把介面和實作類別一塊編譯。
4.修改那個沒有包含m()方法的接口,聲明m()方法為abstract。
5.單獨重新編譯修改過的介面。
6.運行實作類別。

Java8的default方法詳細介紹

上面的情況下類別可以正常運作。但是,不能用修改過的介面重新編譯,但是用老的介面編譯仍然可以運行。接下來


1.修改那個含有abstract方法m()的接口,建立一個default實作。
2.編譯修改後的介面
3.運行類別:失敗。
當兩個介面給同一個方法都提供了default實作的時候,這個方法是無法被呼叫的,除非實作類別也實作了這個default方法(要嘛是直接實現,要嘛是繼承樹上更上層的類做實現)。

Java8的default方法詳細介紹

但是,這個類別是相容的。它可以在使用新介面的情況下被載入,甚至可以執行,只要它沒有呼叫在兩個介面中都有default實作的方法。


實例程式碼:

Java8的default方法詳細介紹

為了示範上面的例子,我給C.java創建了一個測試目錄,它下面還有3個子目錄,用於存放I1.java和I2.java。測試目錄下包含了類別C的源碼C.java。 base目錄包含了可以編譯和執行的那個版本的介面。 I1包含了有default實作的m()方法,I2不包含任何方法。

實作類別包含了main方法,所以我們可以在測試中執行它。它會檢查是否存在命令列參數,這樣,我們就可以很方便的執行呼叫m()和不呼叫m()的測試。

~/github/test$ cat C.java
public class C implements I1, I2 {
  public static void main(String[] args) {
    C c = new C();
    if(args.length == 0 ){
        c.m();
    }
  }
}
~/github/test$ cat base/I1.java
public interface I1 {
  default void m(){
    System.out.println("hello interface 1");
  }
}
~/github/test$ cat base/I2.java
public interface I2 {
}
登入後複製

使用下面的命令列來編譯運行:

~/github/test$ javac -cp .:base C.java
~/github/test$ java -cp .:base C
hello interface 1
登入後複製

compatible目錄包含了有abstract方法m()的I2接口,和未修改的I1接口。

~/github/test$ cat compatible/I2.java
public interface I2 {
  void m();
}
登入後複製

這個不能用來編譯類別C:

~/github/test$ javac -cp .:compatible C.java
C.java:1: error: C is not abstract and does not override abstract method m() in I2
public class C implements I1, I2 {
   ^
1 error
登入後複製

錯誤訊息非常精確。因為我們有前一次編譯獲得的C.class,如果我們編譯compatible目錄下的接口,我們仍然會得到能運行實現類的兩個接口:

~/github/test$ javac compatible/I*.java
~/github/test$ java -cp .:compatible C
hello interface 1
登入後複製

第三個叫做wrong的目錄,包含的I2接口也定義了m()方法:

~/github/test$ cat wrong/I2.java
public interface I2 {
  default void m(){
    System.out.println("hello interface 2");
  }
}
登入後複製

我们应该不厌其烦的编译它。尽管m()方法被定义了两次,但是,实现类仍然可以运行,只要它没有调用那个定义了多次的方法,但是,只要我们调用m()方法,立即就会失败。这是我们使用的命令行参数:

~/github/test$ javac wrong/*.java
~/github/test$ java -cp .:wrong C
Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting
default methods: I1.m I2.m
    at C.m(C.java)
    at C.main(C.java:5)
~/github/test$ java -cp .:wrong C x
~/github/test$
登入後複製

结论

当你把给接口添加了default实现的类库移植到Java 8环境下的时候,一般不会有问题。至少Java8类库开发者给集合类添加default方法的时候就是这么想的。使用你类库的应用程序仍然依赖没有default方法的Java7的类库。当使用和修改多个不同的类库的时候,有很小的几率会发生冲突。如何才能避免呢?

像以前那样设计你的类库。可能依赖default方法的时候不要掉以轻心。万不得已不要使用。明智的选择方法名,避免和其它接口产生冲突。我们将会学习到Java编程中如何使用这个特性做开发。

更多Java8的default方法詳細介紹相关文章请关注PHP中文网!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Java的類負載機制如何起作用,包括不同的類載荷及其委託模型? Java的類負載機制如何起作用,包括不同的類載荷及其委託模型? Mar 17, 2025 pm 05:35 PM

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA

如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存? 如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存? Mar 17, 2025 pm 05:44 PM

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射? 如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射? Mar 17, 2025 pm 05:43 PM

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案? 如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案? Mar 17, 2025 pm 05:46 PM

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)? 如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)? Mar 17, 2025 pm 05:45 PM

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

See all articles