java8 默认方法_Java 8的默认方法:可以做什么和不能做什么?
java8 默認方法
什么是默認方法
在Java 8發行版中,您可以修改接口以添加新方法,以便該接口與實現該接口的類保持兼容。 萬一您開發了一個庫,該庫將由基輔到紐約的幾位程序員使用,那么這非常重要。 在Java 8出現之前,如果您在庫中發布了接口,則您不能添加新方法,而不必冒險在接口中實現的某些應用程序會隨接口的新版本而中斷。
使用Java 8,這種恐懼消失了嗎? 沒有。
向接口添加默認方法可能會使某些類無法使用。
首先讓我們看一下默認方法的要點。
在Java 8中,可以在接口中實現一種方法。 (從Java8開始,靜態方法也可以在接口中實現,但這是另一回事。)在接口中實現的方法稱為默認方法,用關鍵字default表示為修飾符。 當類實現接口時,它可以但不必實現已經在接口中實現的方法。 該類繼承默認實現。 這就是為什么在實現接口的更改時可能無需觸摸類的原因。
多重繼承?
當一個具體的類實現多個(例如兩個)接口并且這些接口實現相同的默認方法時,事情就變得復雜起來。 該類將繼承哪個默認方法? 答案是否定的。 在這種情況下,該類必須自己實現該方法(直接實現或通過繼承更高級別的類)。
當只有一個接口實現默認方法而另一個僅將其聲明為抽象方法時,也是如此。 Java 8試圖受到約束,并避免“隱式”的事情。 如果在多個接口中聲明了這些方法,則不會繼承任何默認實現,則將出現編譯時錯誤。
但是,如果您已經編譯了類,則不會出現編譯時錯誤。 這樣Java 8不一致。 它有其原因,我不想在這里詳述或出于各種原因而進入辯論(例如:發布已結束,辯論時間很長,并且從未在此平臺上使用)。
- 假設您有兩個接口,還有一個實現這兩個接口的類。
- 接口之一實現默認方法m() 。
- 您編譯所有接口和類。
- 您更改不包含方法m()的接口,以將其聲明為抽象方法。
- 僅編譯修改后的接口。
- 運行課程。
在這種情況下,該類將運行。 您不能使用修改后的接口再次對其進行編譯,但是如果它是使用較舊版本進行編譯的:它仍然可以運行。 現在
- 修改具有抽象方法m()的接口并創建默認實現。
- 編譯修改后的接口。
- 運行類:失敗。
當有兩個接口為同一方法提供默認實現時,該方法不能在實現類中調用,除非由該類實現(再次:直接或從另一個類繼承)。
該類是兼容的。 可以使用新界面加載它。 只要兩個接口中都沒有默認實現的方法的調用,它甚至可以開始執行。
樣例代碼
為了演示上述內容,我為類C.java創建了一個測試目錄,并為文件I1.java和I2.java的接口創建了三個子目錄。 測試的根目錄在文件C.java包含類C的源代碼。 目錄base包含適合執行和編譯的接口版本。 I1包含具有默認實現的方法m() 。 接口I2目前不包含任何方法。
該類包含一個main方法,因此我們可以在測試中執行它。 它測試是否有任何命令行參數,因此我們可以輕松地執行它,而無需調用方法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 1compatible目錄包含聲明了方法m()抽象的接口I2版本,并且由于技術原因,它包含未I1.java 。
~/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 1wrong的第三個目錄包含I2版本,該版本還定義了方法m() :
~/github/test$ cat wrong/I2.java public interface I2 {default void m(){System.out.println("hello interface 2");} }我們甚至不應該去編譯它。 即使該方法是雙重定義的,只要不調用該方法,該類仍然可以執行,但是只要我們嘗試調用方法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.mat C.m(C.java)at C.main(C.java:5) ~/github/test$ java -cp .:wrong C x ~/github/test$結論
當您開始將庫移至Java 8并修改接口以添加默認實現時,您可能不會遇到問題。 至少這是Java 8庫開發人員希望將功能方法添加到集合中的方式。 使用您的庫的應用程序仍然依賴沒有默認方法的Java 7庫。 使用和修改不同的庫時,沖突的可能性很小。 怎么避免呢?
像以前一樣設計您的庫API。 不要輕易依賴默認方法的可能性。 他們是不得已的選擇。 明智地選擇名稱,以避免與其他接口沖突。 我們將學習如何使用此功能來開發Java編程。
翻譯自: https://www.javacodegeeks.com/2014/04/java-8-default-methods-what-can-and-can-not-do.html
java8 默認方法
總結
以上是生活随笔為你收集整理的java8 默认方法_Java 8的默认方法:可以做什么和不能做什么?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: aws iam 架构图_使用IAM保护您
- 下一篇: 解除块快捷键(cad解除块快捷键)