1. 程式人生 > 實用技巧 >【JavaSE學習筆記03】介面

【JavaSE學習筆記03】介面

Chapter 6. 介面

介面interface)技術,主要用來描述類具有什麼功能,而並不給出每個功能的具體實現。一個類可以實現implement)一個或多個介面,並在需要介面的地方,隨時使用實現了相應介面的物件。

6.1 介面概述

在Java中,介面不是類,而是對類的一組需求描述,這些類要遵從介面描述的統一格式進行定義。重要的是,介面不能提供哪些功能,絕不能含有例項域,也不能在介面中實現方法、靜態程式碼塊、構造方法。提供例項域和方法實現的任務,應該由實現介面的那個類(可以看做為介面的子類)來完成,實現介面中所有的抽象方法,建立該類物件,就可以呼叫方法了,否則它必須是一個抽象類。

舉個例子,Arrays

類中的sort方法承諾可以對物件陣列進行排序,但要求滿足前提——物件所屬的類必須實現了Comparable介面。

介面是一種引用資料型別,它的內部主要封裝了方法,包含抽象方法(JDK7以前),預設方法和靜態方法(JDK8),私有方法(JDK9)。

6.2 定義格式與基本實現

介面的定義格式:(使用interface關鍵字)

public interface 介面名稱{ 
    //抽象方法
    //預設方法
    //靜態方法
    //私有方法
}

在使用IDEA建立interface時,應該新建interface而不是class

但是,換成關鍵字interface之後,.java檔案編譯生成的位元組碼檔案仍然為.class

類與介面的關係為實現關係,即類實現介面,該類可以稱為介面的實現類,也可稱為介面的子類。實現使用implements關鍵字(注意s

class 類名 implements 介面名{
    //重寫介面中抽象方法(必須!)
    //重寫介面中預設方法(可選)
}

6.2.1 含有抽象方法

抽象方法: 使用 abstract 關鍵字修飾,沒有方法體。該方法供子類實現使用

定義介面:

public interface LiveAble{ 
    public abstract void eat();//定義抽象方法
    public abstract void sleep();
}

定義實現類:

public class Animal implements LiveAble{
    @Override
    public void eat(){
        System.out.println("獲取食物");
    }
    @Override
    public void sleep(){
        System.out.println("地上睡覺");
    } 
}

TIPS:對於IDEA而言,滑鼠選中整個介面名稱,按alt + Enter鍵就能方便覆寫:

定義測試類:

public class InterfaceDemo{
    public static void main(String[] args){
        Animal a = new Animal(); //建立子類物件
        a.eat(); a.sleep();
    }
}

6.2.2 含有預設方法

預設方法:使用default修飾,不可省略,供子類呼叫或者子類覆寫

定義介面:

public interface LiveAble{
    public default void fly(){
        System.out.println("天上飛");
    }
}

實現類可以繼承,可以重寫,二選一,但是隻能通過實現類的物件來呼叫。

  1. 繼承預設方法來定義實現類:

    public class Animal implements LiveAble{
        //繼承,什麼都不用寫,直接呼叫
    }
    
  2. 重寫預設方法來定義實現類:

    public class Animal implements LiveAble{
        @Override
        public void fly(){
            System.out.println("自由自在地飛");
        }
    }
    

定義測試類:

public class InterfaceDemo{
    public static void main(String[] args){
        Animal a = new Animal(); //建立子類物件
        a.fly(); //1 的輸出結果為:天上飛;2 的輸出結果為:自由自在地飛。
    }
}

6.2.3 含有靜態方法

靜態方法:使用static修飾,供介面直接呼叫。

定義介面:

public interface LiveAble{
    public static void run(){
        System.out.println("跑起來!");
    }
}

靜態與.class檔案相關,只能使用介面名呼叫,不可通過實現類的類名或者實現類的物件呼叫。

定義實現類:

public class Animal implements LiveAble{
    //無法重寫靜態方法!
}

定義測試類:

public class InterfaceDemo{
    public static void main(String[] args){
        //Animal.run(); //錯誤寫法,無法繼承方法也不能呼叫。
        LiveAble.run();
    }
}

6.2.4 含有私有方法

若一個介面中有多個預設方法,且方法中有重複的內容,那麼可以抽取出來,封裝到私有方法中,供預設方法去呼叫。從設計的角度來講,私有的方法是對預設方法和靜態方法的輔助。

  • 普通私有方法:只有預設方法可以呼叫。

    private 返回值型別 方法名稱(引數列表){
        方法體
    }
    
  • 靜態私有方法:預設方法和靜態方法可以呼叫。

    private static 返回值型別 方法名稱(引數列表){
        方法體
    }
    

舉例定義介面:

public interface LiveAble{
	public default void eat(){
        System.out.println("Eat something...");
        methodCommon();
    }
    public default void sleep(){
        System.out.println("Go to sleep...");
        methodCommon();
    }
    private void methodCommon(){ //該方法是專門為了上面兩個方法所抽取出來的,不應被實現類訪問。
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }
}

6.2.5 含有常量

介面當中其實也可以定義“成員變數”,但是必須使用public static final三個關鍵字進行修飾,從效果上看就是介面的“常量”。

定義介面:

public interface LiveAble{
    public static final int num = 233;
    //public 說明介面內外部都可使用;static 使得num與物件無關;final 使得num不可變
}

注意,介面當中的常量必須進行賦值!

6.3 實現多個介面

6.3.1 介面與抽象類的比較

使用抽象類表示通用屬性會存在問題——每個類只能拓展於一個類。不同於C++的多繼承特性,為了避免將語言變得非常複雜或者效率降低,Java語言利用介面機制,來實現多繼承的大部分功能,由此每個類可以同時實現多個介面

6.3.2 定義格式

public class 例項類名 implements 介面A, 介面B{
    //覆蓋所有抽象方法
}

注意事項:

  1. 若實現類所實現的多個介面中,存在重複的抽象方法,那麼只需要覆蓋重寫一次即可。
  2. 若實現類所實現的多個介面中,存在重複的預設方法,那麼實現類一定要對衝突的預設方法進行覆寫。(也就說,不能直接繼承這些預設方法)
  3. 一個類中若直接父類當中的方法,與介面當中的預設方法產生了衝突,優先使用父類當中的方法。

6.4 介面之間的多繼承

類與類之間是單繼承的,而介面與介面之間是多繼承的。

介面的繼承也是使用extends關鍵字。

定義父介面:

public interface A(){
	public default void method(){
        System.out.println("AAA");
    }
} 
public interface B(){
    public default void method(){
        System.out.println("BBB");
    }
}

定義子介面:

public interface C extends A, B{
    @Override
    public default void method(){
        System.out.println("23333");
    }
}

注意事項:

  1. 如果父介面中的預設方法有重名的,那麼子介面需要重寫一次。
  2. 子介面重寫預設方法時,default關鍵字可以保留。但是,子類重寫預設方法時,default關鍵字不可以保留。