Java接口默認方法:Java 8新特性,接口也能有默認實現

傳統接口的“痛點”

在Java 8之前,接口的作用更像是一個“契約”——接口中只能定義抽象方法,所有實現類必須“完完全全”地實現這些抽象方法。如果我們想在接口中新增一個方法,那所有實現該接口的類都必須手動添加這個新方法的實現,否則代碼會編譯報錯。這在接口需要頻繁擴展時非常不方便,比如一個框架接口突然需要增加新功能,所有依賴它的類都得跟着改,很容易出問題。

接口默認方法的“救場”

Java 8爲了解決這個問題,引入了默認方法(Default Method)。簡單來說,默認方法是接口中帶具體實現的方法,使用 default 關鍵字修飾。有了默認方法後,接口不再只能定義抽象方法,還能提供一些“默認行爲”,實現類可以直接使用這些默認方法,不需要強制重寫。

如何定義和使用默認方法?

默認方法的語法很簡單,只需在方法前加上 default 關鍵字,並給出具體實現即可。

示例代碼:

// 定義一個接口,包含默認方法
interface Greeting {
    // 抽象方法(必須由實現類重寫)
    void sayHello();

    // 默認方法(接口自帶實現,實現類可直接使用)
    default void sayGoodbye() {
        System.out.println("Goodbye!");
    }
}

// 實現接口
class EnglishGreeting implements Greeting {
    @Override
    public void sayHello() {
        System.out.println("Hello!");
    }

    // 這裏可以選擇是否重寫默認方法(可選)
    // @Override
    // public void sayGoodbye() {
    //     System.out.println("Bye-bye!");
    // }
}

public class Main {
    public static void main(String[] args) {
        Greeting greeter = new EnglishGreeting();
        greeter.sayHello();   // 輸出:Hello!
        greeter.sayGoodbye(); // 輸出:Goodbye!(直接使用默認實現)
    }
}

在這個例子中:
- sayHello() 是抽象方法,實現類 EnglishGreeting 必須重寫。
- sayGoodbye() 是默認方法,實現類無需手動實現,可直接調用。

實現類如何重寫默認方法?

如果實現類覺得接口的默認方法不符合自身需求,可以像重寫父類方法一樣,重寫默認方法。只需要在實現類中用 @Override 註解重新定義該方法即可。

示例代碼:

class ChineseGreeting implements Greeting {
    @Override
    public void sayHello() {
        System.out.println("你好!");
    }

    @Override
    public void sayGoodbye() {
        System.out.println("再見!"); // 重寫默認方法
    }
}

public class Main {
    public static void main(String[] args) {
        Greeting chineseGreeter = new ChineseGreeting();
        chineseGreeter.sayGoodbye(); // 輸出:再見!(使用重寫後的默認方法)
    }
}

注意:默認方法的衝突問題

如果一個類同時實現了多個接口,且這些接口中包含同名、同參數的默認方法,就會產生衝突。此時實現類必須顯式重寫該方法,否則編譯報錯。

示例代碼:

interface A {
    default void method() {
        System.out.println("A's method");
    }
}

interface B {
    default void method() {
        System.out.println("B's method");
    }
}

// 類C同時實現A和B,會衝突!
class C implements A, B {
    // 必須顯式重寫method()來解決衝突
    @Override
    public void method() {
        System.out.println("C's method");
    }
}

如果沒有重寫,編譯器會報錯:The type C must implement the inherited abstract method...(或類似衝突提示)。

總結:默認方法的意義

默認方法讓接口變得更靈活:
1. 擴展接口不破壞現有實現:新增方法時,舊實現類無需修改,直接繼承默認方法。
2. 接口更像“帶默認行爲的契約”:可以給接口提供基礎功能,實現類按需重寫或直接使用。
3. 避免了抽象類的缺點:抽象類需要繼承,而接口可以多實現;默認方法讓接口兼具“可擴展”和“契約性”。

小試牛刀

試着定義一個帶默認方法的接口 Shape,包含抽象方法 getArea() 和默認方法 printInfo()(默認打印“這是一個圖形”),然後實現一個 Circle 類繼承該接口並測試。

提示:
- 接口 Shapedefault void printInfo() { System.out.println("這是一個圖形"); }
- 類 Circle:實現 getArea() 方法,例如計算半徑爲5的圓面積(πr²),並調用默認方法。

默認方法是Java 8的重要特性,它讓接口從“純抽象契約”升級爲“可擴展的工具”,是面向對象設計中接口靈活性的一次重要提升。掌握它後,寫代碼時會更輕鬆!

小夜