1. 程式人生 > 其它 >小白學集合之看ArrayList和LinkedList原始碼

小白學集合之看ArrayList和LinkedList原始碼

技術標籤:## java

抽象類和介面

抽象類

定義:抽象類前使用abstract關鍵字修飾,則該類為抽象類。

使用抽象類要注意以下幾點:

1. 抽象類是約束子類必須有什麼方法,而並不關注子類如何實現這些方法。

2. 抽象類應用場景:

a. 在某些情況下,某個父類只是知道其子類應該包含怎樣的方法,但無法準確知道這些子類如何實現這些方法(可實現動態多型)。

b. 從多個具有相同特徵的類中抽象出一個抽象類,以這個抽象類作為子類的模板,從而避免子類設計的隨意性。

​ 3.抽象類定義抽象方法,只有宣告,不需要實現。抽象方法沒有方法體以分號結束,抽象方法必須用abstract關鍵字來修飾。如:

public abstract class Fruit {
    //抽象方法 方法體以分號結束,只有宣告沒有實現
    public abstract void price();
}
 4.包含抽象方法的類是抽象類。抽象類中可以包含普通的方法,也可以沒有抽象方法。如:
public abstract class Fruit {
    //抽象類裡面可以沒有抽象方法
    public void message(){
        System.out.println("我是抽象類的普通方法");
    }//抽象類的普通方法
}
5.抽象類不能直接建立,可以定義引用變數來指向子類物件,來實現抽象方法。以上述的Fruit抽象類為例:
package OOP;

public class apple extends Fruit{
    //繼承抽象類的子類必須重寫抽象方法
    @Override
    public void price() {
        System.out.println("我是抽象類的子類,我重寫了抽象類的方法");
    }
}
package OOP;

public abstract class Fruit {
    //抽象方法 方法體以分號結束,只有宣告沒有實現
    public abstract void price();
    //抽象類裡面可以沒有抽象方法
public void message(){ System.out.println("我是抽象類的普通方法"); }//抽象類的普通方法 }
public class test {
    public static void main(String[] args) {
        //Fruit fruit = new Fruit(); 報錯,抽象類無法直接建立
        Fruit fruit = new apple();//定義引用變數來指向子類
        fruit.message();
        fruit.price();
    }
}

結果:
在這裡插入圖片描述

介面

1.概念

介面可以理解為一種特殊的類,由全域性常量和公共的抽象方法所組成。也可理解為一個特殊的抽象類,因為它含有抽象方法。

如果說類是一種具體實現體,而介面定義了某一批類所需要遵守的規範,介面不關心這些類的內部資料,也不關心這些類裡方法的實現細節,它只規定這些類裡必須提供的某些方法。(這裡與抽象類相似)

2.介面定義的基本語法

[修飾符] [abstract] interface 介面名 [extends父介面1,2…](多繼承){

0…n常量 (public static final)

0…n 抽象方法(public abstract)

}

其中[ ]裡的內容表示可選項,可以寫也可以不寫;介面中的屬性都是常量,即使定義時不新增public static final 修飾符,系統也會自動加上;介面中的方法都是抽象方法,即使定義時不新增public abstract修飾符,系統也會自動加上。

3.使用介面

一個類可以實現一個或多個介面,實現介面使用implements關鍵字。java中一個類只能繼承一個父類,是不夠靈活的,通過實現多個介面可以補充。

繼承父類實現介面的語法為:

[修飾符] class 類名 extends 父類 implements 介面1,介面2…{

類體部分//如果繼承了抽象類,需要實現繼承的抽象方法;要實現介面中的抽象方法

}

注意:如果要繼承父類,繼承父類必須在實現介面之前,即extends關鍵字必須在implements關鍵字前

補充說明:通常我們在命名一個介面時,經常以I開頭,用來區分普通的類。如:IPlayGame

以下我們來補充在上述抽象類中的例子,我們之前已經定義了一個抽象類Telephone和子類Phone,這裡我們再建立一個IPlayGame的介面,然後在原來定義的兩個類稍作修改,程式碼如下:

public interface IEatable {
    //abstract 關鍵字可以省略,系統會自動加上
    public String tester = "Chinese";
    //static final關鍵字可以省略,系統會自動加上
    public void result();
}
public class banana extends Fruit implements IEatable{
    //繼承抽象類的子類必須重寫抽象方法
    @Override
    public void price() {
        System.out.println("我有banana,我重寫了抽象類的方法,我將被測試者吃掉");
    }
    //一個類如果實現了一個介面,則要實現該介面的所有方法
    @Override
    public void result() {
        System.out.println("我重寫了介面的方法,測試者來了");
    }
}
public class test {
    public static void main(String[] args) {
        IEatable eatable = new banana();//用介面的引用指向子類的物件
        eatable.result();//呼叫介面的方法
        System.out.println(eatable.tester);//輸出介面的常量
    }
}

執行結果:

在這裡插入圖片描述

4.介面和匿名內部類配合使用

介面在使用過程中還經常和匿名內部類配合使用。匿名內部類就是沒有沒名字的內部類,多用於關注實現而不關注實現類的名稱。

語法格式:

Interface i = new interface(){
    pubulic void method{
        System.out.println(“利用匿名內部類實現介面1);
    }
};
i.method();

另一種寫法:(直接把方法的呼叫寫在匿名內部類的最後,android開發常見)

Interface i = new interface(){
Public void method{
        System.out.println(“利用匿名內部類實現介面1);
	}
}.method();

抽象類和介面的區別

我們在多型的學習過程中認識到抽象類和介面都是實現java多型特性的關鍵部分,兩者都包含抽象方法,只關注方法的宣告而不關注方法的具體實現,那麼這兩者又有什麼區別呢??我們在編寫java程式的時候又該如何抉擇呢?

參考博文:http://www.cnblogs.com/felixzh/p/5938544.html

(1)語法層面上的區別

1.一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。
 2.抽象類中的成員變數可以是各種型別的,而介面中的成員變數只能是public static final型別的;且必須給其初值,所以實現類中不能重新定義,也不能改變其值;抽象類中的變數預設是 friendly 型,其值可以在子類中重新定義,也可以重新賦值。
 3.抽象類中可以有非抽象方法,介面中則不能有非抽象方法。
 4.介面可以省略abstract 關鍵字,抽象類不能。
 5.介面中不能含有靜態程式碼塊以及靜態方法,而抽象類可以有靜態程式碼塊和靜態方法;

(2)設計層面上的區別

1)抽象類是對一種事物的抽象,即對類抽象,而介面是對行為的抽象。抽象類是對整個類整體進行抽象,包括屬性、行為,但是介面卻是對類區域性(行為)進行抽象。舉個簡單的例子,飛機和鳥是不同類的事物,但是它們都有一個共性,就是都會飛。那麼在設計的時候,可以將飛機設計為一個類Airplane,將鳥設計為一個類Bird,但是不能將飛行 這個特性也設計為類,因此它只是一個行為特性,並不是對一類事物的抽象描述。此時可以將 飛行 設計為一個介面Fly,包含方法fly( ),然後Airplane和Bird分別根據自己的需要實現Fly這個介面。然後至於有不同種類的飛機,比如戰鬥機、民用飛機等直接繼承Airplane即可,對於鳥也是類似的,不同種類的鳥直接繼承Bird類即可。從這裡可以看出,繼承是一個 "是不是"的關係,而 介面 實現則是 "有沒有"的關係。如果一個類繼承了某個抽象類,則子類必定是抽象類的種類,而介面實現則是有沒有、具備不具備的關係,比如鳥是否能飛(或者是否具備飛行這個特點),能飛行則可以實現這個介面,不能飛行就不實現這個介面。

2)設計層面不同,抽象類作為很多子類的父類,它是一種模板式設計。而介面是一種行為規範,它是一種輻射式設計。什麼是模板式設計?最簡單例子,大家都用過ppt裡面的模板,如果用模板A設計了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它們的公共部分需要改動,則只需要改動模板A就可以了,不需要重新對ppt B和ppt C進行改動。而輻射式設計,比如某個電梯都裝了某種報警器,一旦要更新報警器,就必須全部更新。也就是說對於抽象類,如果需要新增新的方法,可以直接在抽象類中新增具體的實現,子類可以不進行變更;而對於介面則不行,如果介面進行了變更,則所有實現這個介面的類都必須進行相應的改動。

下面看一個網上流傳最廣泛的例子:門和警報的例子:門都有open( )和close( )兩個動作,此時我們可以定義通過抽象類和介面來定義這個抽象概念:

abstract class Door {
	public abstract void open();
    public abstract void close();
 }

或者:

interface Door {
	public abstract void open();
	public abstract void close(); 
}

但是現在如果我們需要門具有報警alarm( )的功能,那麼該如何實現?下面提供兩種思路:

1)將這三個功能都放在抽象類裡面,但是這樣一來所有繼承於這個抽象類的子類都具備了報警功能,但是有的門並不一定具備報警功能;

2)將這三個功能都放在接口裡面,需要用到報警功能的類就需要實現這個介面中的open( )和close( ),也許這個類根本就不具備open( )和close( )這兩個功能,比如火災報警器。

從這裡可以看出, Door的open() 、close()和alarm()根本就屬於兩個不同範疇內的行為,open()和close()屬於門本身固有的行為特性,而alarm()屬於延伸的附加行為。因此最好的解決辦法是單獨將報警設計為一個介面,包含alarm()行為,Door設計為單獨的一個抽象類,包含open和close兩種行為。再設計一個報警門繼承Door類和實現Alarm介面。

interface Alram {
     void alarm();
}  
abstract class Door {
     void open();
     void close();
}
class AlarmDoor extends Door implements Alarm {
     void oepn() {
       //....
     }
     void close() {
       //....
     }
     void alarm() {
       //....
     }
}

學習參考:

https://www.cnblogs.com/rove888/p/9936109.html