1. 程式人生 > 實用技巧 >2020重新出發,JAVA基礎,抽象類&介面

2020重新出發,JAVA基礎,抽象類&介面

@目錄

抽象類&介面

抽象類

Java語言提供了兩種類,分別為具體類和抽象類。前面學習接觸的類都是具體類。下面來說一下抽象類。

在面向物件的概念中,所有的物件都是通過類來描繪的,但是反過來,並不是所有的類都是用來描繪物件的,如果一個類中沒有包含足夠的資訊來描繪一個具體的物件,這樣的類就是抽象類

抽象類除了不能例項化物件之外,類的其它功能依然存在,成員變數、成員方法和構造方法的訪問方式和普通類一樣。

由於抽象類不能例項化物件,所以抽象類必須被繼承,才能被使用。也是因為這個原因,通常在設計階段決定要不要設計抽象類。

父類包含了子類集合的常見的方法,但是由於父類本身是抽象的,所以不能使用這些方法。

在Java中抽象類表示的是一種繼承關係,一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。

在 Java 中抽象類的語法格式如下:

<abstract>class<class_name> {
    <abstract><type><method_name>(parameter-iist);
}

其中,abstract 表示該類或該方法是抽象的;class_name 表示抽象類的名稱;method_name 表示抽象方法名稱,parameter-list 表示方法引數列表。

抽象方法

如果一個方法使用 abstract 來修飾,則說明該方法是抽象方法,抽象方法只有宣告沒有實現。需要注意的是 abstract 關鍵字只能用於普通方法,不能用於 static 方法或者構造方法中。

抽象方法的 3 個特徵如下:

  1. 抽象方法沒有方法體
  2. 抽象方法必須存在於抽象類中
  3. 子類重寫父類時,必須重寫父類所有的抽象方法

注意:在使用 abstract 關鍵字修飾抽象方法時不能使用 private 修飾,因為抽象方法必須被子類重寫,而如果使用了 private 宣告,則子類是無法重寫的。

繼承抽象方法的子類必須重寫該方法。否則,該子類也必須宣告為抽象類。最終,必須有子類實現該抽象方法,否則,從最初的父類到最終的子類都不能用來例項化物件。

抽象類的定義和使用規則如下:

  1. 抽象類和抽象方法都要使用 abstract 關鍵字宣告。
  2. 如果一個方法被宣告為抽象的,那麼這個類也必須宣告為抽象的。一個抽象類中,可以有 0~n 個抽象方法,以及 0~n 個具體方法。
  3. 抽象類不能例項化,也就是不能使用 new 關鍵字建立物件。

抽象類總結

  1. 抽象類不能被例項化(初學者很容易犯的錯),如果被例項化,就會報錯,編譯無法通過。只有抽象類的非抽象子類可以建立物件。
  2. 抽象類中不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
  3. 抽象類中的抽象方法只是宣告,不包含方法體,就是不給出方法的具體實現也就是方法的具體功能。
  4. 構造方法,類方法(用 static 修飾的方法)不能宣告為抽象方法。
  5. 抽象類的子類必須給出抽象類中的抽象方法的具體實現,除非該子類也是抽象類。

介面

抽象類是從多個類中抽象出來的模板,如果將這種抽象進行的更徹底,則可以提煉出一種更加特殊的“抽象類”—介面(Interface)。介面是 Java 中最重要的概念之一,它可以被理解為一種特殊的類,不同的是介面的成員沒有執行體,是由全域性常量和公共的抽象方法組成。

介面(Interface),在JAVA程式語言中是一個抽象型別,是抽象方法的集合,介面通常以interface來宣告。一個類通過繼承介面的方式,從而來繼承介面的抽象方法。

定義介面

Java 介面的定義方式與類基本相同,不過介面定義使用的關鍵字是 interface,介面定義的語法格式如下:

[public] interface interface_name [extends interface1_name[, interface2_name,…]] {
    // 介面體,其中可以包含定義常量和宣告方法
    [public] [static] [final] type constant_name = value;    // 定義常量
    [public] [abstract] returnType method_name(parameter_list);    // 宣告方法
}

對以上語法的說明如下:

  • public 表示介面的修飾符,當沒有修飾符時,則使用預設的修飾符,此時該介面的訪問許可權僅侷限於所屬的包;
  • interface_name 表示介面的名稱。介面名應與類名採用相同的命名規則,即如果僅從語法角度來看,介面名只要是合法的識別符號即可。如果要遵守 Java 可讀性規範,介面名應由多個有意義的單詞連綴而成,每個單詞首字母大寫,單詞與單詞之間無需分隔符。
  • extends 表示介面的繼承關係;
  • interface1_name 表示要繼承的介面名稱;
  • constant_name 表示變數名稱,一般是 static 和 final 型的;
  • returnType 表示方法的返回值型別;
  • parameter_list 表示引數列表,在介面中的方法是沒有方法體的。

注意:一個介面可以有多個直接父介面,但介面只能繼承介面,不能繼承類

介面對於其宣告、變數和方法都做了許多限制,這些限制作為介面的特徵歸納如下:

  • 具有 public 訪問控制符的介面,允許任何類使用;沒有指定 public 的介面,其訪問將侷限於所屬的包。
  • 方法的宣告不需要其他修飾符,在介面中宣告的方法,將隱式地宣告為公有的(public)和抽象的(abstract)。
  • 在 Java 介面中宣告的變數其實都是常量,介面中的變數宣告,將隱式地宣告為 public、static 和 final,即常量,所以介面中定義的變數必須初始化。
  • 介面沒有構造方法,不能被例項化。例如:
public interface A {    publicA(){…}    // 編譯出錯,介面不允許定義構造方法}

一個介面不能夠實現另一個介面,但它可以繼承多個其他介面。子介面可以對父介面的方法和常量進行重寫。例如:

public interface StudentInterface extends PeopleInterface {    
    // 介面 StudentInterface 繼承 PeopleInterface    
    int age = 25;    // 常量age重寫父介面中的age常量    
    void getInfo();    // 方法getInfo()重寫父介面中的getInfo()方法}

實現介面

介面的主要用途就是被實現類實現,一個類可以實現一個或多個介面,繼承使用 extends 關鍵字,實現則使用 implements 關鍵字。因為一個類可以實現多個介面,這也是 Java 為單繼承靈活性不足所作的補充。類實現介面的語法格式如下:

<public> class <class_name> [extends superclass_name] [implements interface1_name[, interface2_name…]] {
    // 主體
}

對以上語法的說明如下:

  • public:類的修飾符;
  • superclass_name:需要繼承的父類名稱;
  • interface1_name:要實現的介面名稱。

實現介面需要注意以下幾點:

  • 實現介面與繼承父類相似,一樣可以獲得所實現接口裡定義的常量和方法。如果一個類需要實現多個介面,則多個介面之間以逗號分隔。
  • 一個類可以繼承一個父類,並同時實現多個介面,implements 部分必須放在 extends 部分之後。
  • 一個類實現了一個或多個介面之後,這個類必須完全實現這些接口裡所定義的全部抽象方法(也就是重寫這些抽象方法);否則,該類將保留從父介面那裡繼承到的抽象方法,該類也必須定義成抽象類。

介面與類的區別:

  • 介面並不是類,編寫介面的方式和類很相似,但是它們屬於不同的概念。
  • 類描述物件的屬性和方法
  • 介面則包含類要實現的方法
  • 除非實現介面的類是抽象類,否則該類要定義介面中的所有方法。
  • 介面無法被例項化,但是可以被實現
  • 一個實現介面的類,必須實現介面內所描述的所有方法,否則就必須宣告為抽象類。
  • 在 Java 中,介面型別可用來宣告一個變數,他們可以成為一個空指標,或是被繫結在一個以此介面實現的物件。

介面特性

  • 介面中每一個方法也是隱式抽象的,介面中的方法會被隱式的指定為 public abstract(只能是 public abstrac)。
  • 介面中可以含有變數,但是介面中的變數會被隱式的指定為 public static final 變數(並且只能是 public)。
  • 介面中的方法是不能在介面中實現的,只能由實現介面的類來實現介面中的方法。

抽象類和介面的區別

  • 抽象類中的方法可以有方法體,就是能實現方法的具體功能,但是介面中的方法不行。
  • 抽象類中的成員變數可以是各種型別的,而介面中的成員變數只能是 public static final 型別的。
  • 介面中不能含有靜態程式碼塊以及靜態方法(用 static 修飾的方法),而抽象類是可以有靜態程式碼塊和靜態方法。
  • 一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。

:JDK 1.8 以後,接口裡可以有靜態方法和方法體了。