自學Java之day10_java接口

接口概述

接口,是Java語言中一種引用類型,是方法的集合,如果說類的內部封裝了成員變量、構造方法和成員方法,那麼 接口的內部主要就是封裝了方法,包含抽象方法(JDK 7及以前),默認方法和靜態方法(JDK 8),私有方法 JDK 9)。 接口的定義,它與定義類方式相似,但是使用 interface 關鍵字。它也會被編譯成.class文件,但一定要明確它並 不是類,而是另外一種引用數據類型。 引用數據類型:數組,類,接口。 接口的使用,它不能創建對象,但是可以被實現( implements ,類似於被繼承)。一個實現接口的類(可以看做 是接口的子類),需要實現接口中所有的抽象方法,創建該類對象,就可以調用方法了,否則它必須是一個抽象 類。 接口就是多個類的公共的規範標準。

接口的定義

定義接口的格式:

public interface 接口名稱 {

             // 抽象方法

             // 默認方法

             // 靜態方法

             // 私有方法

}

備註:換成了關鍵字interface之後,編譯生成的字節碼文件仍然是:.java --> .class。

如果是(JDK 7及以前),那麼接口中可以包含的內容有:

  • 常量
  • 抽象方法

定義抽象方法

格式:

  • public abstract 返回值類型 方法名稱(參數列表);

例如:

package demo01;

public interface DemoInterface01 {
    //定義抽象方法
    public abstract void method1();
    //定義抽象方法
    abstract void method2();
    //定義抽象方法
    void method3();
    //定義抽象方法
    public void method4();
}

注意事項:

  • 接口當中的抽象方法,修飾符必須是兩個固定的關鍵字:public abstract
  • 這兩個關鍵字修飾符,可以選擇性地省略。
  • 方法的三要素,可以根據業務需要隨意定義

定義常量

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

格式:

  • public static final 數據類型 常量名稱 = 數據值;

例如:

public interface MyInterfaceConst {

    // 這其實就是一個常量,一旦賦值,不可以修改
    public static final int NUM_OF_MY_CLASS = 12;

}

注意事項:

  • 接口當中的常量,可以省略public static final,注意:不寫也照樣是這樣。
  • 接口當中的常量,必須進行賦值;不能不賦值。
  • 接口中常量的名稱,使用完全大寫的字母,用下劃線進行分隔。(推薦命名規則)任何

接口的實現

類與接口的關係爲實現關係,即類實現接口,該類可以稱爲接口的實現類,也可以稱爲接口的子類。實現的動作類 似繼承,格式相仿,只是關鍵字不同,實現使用 implements 關鍵字。 非抽象子類實現接口: 必須重寫接口中所有抽象方法,如果繼承了接口的默認方法,即可以直接調用,也可以重寫。

接口使用步驟:

1: 接口不能直接使用,必須有一個“實現類”來“實現”該接口。
格式:
public class 實現類名稱 implements 接口名稱 {
    // ...
}
2:接口的實現類必須覆蓋重寫(實現)接口中所有的抽象方法。
3: 創建實現類的對象,進行使用。

注意事項:

  • 如果實現類並沒有覆蓋重寫接口中所有的抽象方法,那麼這個實現類自己就必須是抽象類。

代碼舉例:

定義接口MyInterface01

package myDemo01;

public interface MyInterface01 {
    //定義接口常量
    public static final int value = 18;
    //定義接口抽象方法
    public abstract void print();

}

定義接口實現類MyInterface01Imp

package myDemo01;

//1. 接口不能直接使用,必須有一個“實現類”來“實現”該接口。
public class MyInterface01Imp implements MyInterface01 {
//2:接口的實現類必須覆蓋重寫(實現)接口中所有的抽象方法。
    @Override
    public void print() {
        System.out.println("我接口中的常量值是"+value);
    }
}

定義測試類Interface01Test

package myDemo01;

public class Interface01Test {
    public static void main(String[] args) {
        //3: 創建實現類的對象,進行使用。
        MyInterface01Imp imp = new MyInterface01Imp();
        //使用實現類中的默認方法
        imp.print();
        //訪問接口中的常量
        System.out.println(MyInterface01.value);
    }
}

代碼執行後的結果

從Java 8開始,接口裏還可以定義默認方法。

格式:
public default 返回值類型 方法名稱(參數列表) {
    方法體
}

備註:接口當中的默認方法,可以解決接口升級的問題。

默認方法如何使用:

  • 默認方法可以繼承,可以重寫,二選一,但是隻能通過實現類的對象來調用。

代碼舉例

定義接口MyInterface02

package myDemo01;

public interface MyInterface02 {

    //定義默認方法
    public default void defaultMethod() {
        System.out.println("我是老接口");
    }
}

定義實現類MyInterface02ImpA繼承接口中的默認方法

package myDemo01;

//定義實現類,實現接口
public class MyInterface02ImpA implements MyInterface02 {
//默認方法可以繼承
}

定義實現類MyInterface02ImpB重寫接口中的默認方法

package myDemo01;

public class MyInterface02ImpB implements MyInterface02 {
    // 重寫默認方法

    @Override
    public void defaultMethod() {
        System.out.println("接口升級了");
    }
}

定義測試類Interface02Test

package myDemo01;

public class Interface02Test {
    public static void main(String[] args) {
        //創建實現類對象
        MyInterface02ImpA impA = new MyInterface02ImpA();
        // 調用默認方法,實際運行的是接口中繼承下來的方法
        impA.defaultMethod();
        // 創建了實現類對象
        MyInterface02ImpB impB = new MyInterface02ImpB();
        // 調用,默認方法,實際運行的是右側實現類(重寫之後的方法)。
        impB.defaultMethod();
    }
}

代碼執行後的結果

從Java 8開始,接口當中還允許定義靜態方法。

格式:
public static 返回值類型 方法名稱(參數列表) {
    方法體
}

注意:靜態方法也是有方法體

靜態方法的使用:

  • 靜態與.class 文件相關,只能使用接口名調用,不可以通過實現類的類名或者實現類的對象調用
  • 格式:接口名稱.靜態方法名(參數);
  • 靜態方法無法重寫

代碼舉例

定義接口MyInterface03

package myDemo01;

public interface MyInterface03 {
    public static void method() {
        System.out.println("我是接口中的靜態方法");
    }
}

定義接口實現類MyInterface03Imp

package myDemo01;

public class MyInterface03Imp implements MyInterface03 {
    // 無法重寫靜態方法
}

定義測試類Interface03Test

package myDemo01;

public class Interface03Test {
    public static void main(String[] args) {
        // 創建了實現類對象
        MyInterface03Imp imp = new MyInterface03Imp();

        // 錯誤寫法!實現類調用靜態方法  imp.method;

        // 直接通過接口名稱調用靜態方法
        MyInterface03.method();

    }
}

代碼執行後結果

從Java 9開始,接口當中還允許定義私有方法

如果一個接口中有多個默認方法,並且方法中有重複的內容,那麼可以抽取出來,封裝到私有方法中,供默認方法 去調用。從設計的角度講,私有的方法是對默認方法和靜態方法的輔助。

1. 普通私有方法,解決多個默認方法之間重複代碼問題
格式:
private 返回值類型 方法名稱(參數列表) {
    方法體
}

2. 靜態私有方法,解決多個靜態方法之間重複代碼問題
格式:
private static 返回值類型 方法名稱(參數列表) {
    方法體
}

私有方法的使用

  • 私有方法:只有在接口當中的默認方法裏調用。
  • 私有靜態方法:只有在接口當中的默認方法和靜態方法裏調用。

​​​​​​​代碼舉例

定義接口MyInterface04

package myDemo01;

public interface MyInterface04 {
    //定義默認方法
    public default void methodDefault1() {
        //私有方法只有接口中的默認方法可以調用。
        methodPrivate();
        //私有靜態方法:接口中的默認方法可以調用
        methodStaticPrivate();
    }

    public default void methodDefault2() {
        methodPrivate();
        methodStaticPrivate();

    }

    //定義私有方法
    private void methodPrivate() {
        System.out.println("我是私有方法,我抽取了默認方法中的重複代碼");
    }

    //定義靜態方法
    public static void methodStatic1() {
        //私有靜態方法:接口中的靜態方法也可以調用
        methodStaticPrivate();
    }

    public static void methodStatic2() {
        methodStaticPrivate();
    }

    //定義私有靜態方法
    private static void methodStaticPrivate() {
        System.out.println("我是私有靜態方法,我抽取了靜態方法中的重複代碼");

    }
}

 定義接口實現類MyInterface04Imp

package myDemo01;

public class MyInterface04Imp implements MyInterface04 {
}

定義接口的測試類Interface04Tes

package myDemo01;

public class Interface04Test {
    public static void main(String[] args) {
        //創建接口實現類對象
        MyInterface04Imp imp = new MyInterface04Imp();
        //調用默認方法
        imp.methodDefault1();
        System.out.println("===========");
        imp.methodDefault2();
        System.out.println("===========");
        //調用接口中靜態方法
        MyInterface04.methodStatic1();
        System.out.println("===========");
        MyInterface04.methodStatic2();
    }
}

代碼執行後的結果

使用接口的時候,需要注意:

1:接口是沒有靜態代碼塊或者構造方法的。因爲沒有構造方法,不能創建對象。
2:一個類的直接父類是唯一的,但是一個類可以同時實現多個接口。
格式:
public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
    // 覆蓋重寫所有抽象方法
}
3: 如果實現類所實現的多個接口當中,存在重複的抽象方法,那麼只需要覆蓋重寫一次即可。
4:如果實現類沒有覆蓋重寫所有接口當中的所有抽象方法,那麼實現類就必須是一個抽象類。
5:如果實現類鎖實現的多個接口當中,存在重複的默認方法,那麼實現類一定要對衝突的默認方法進行覆蓋重寫。
6:一個類如果直接父類當中的方法,和接口當中的默認方法產生了衝突,優先用父類當中的方法。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章