標籤:java 抽象類別 介面 區別 不同
抽象類別(abstract class):含有abstract修飾符的類。它不能建立執行個體對象;含有abstract方法的類必須定義為abstract class;abstract class類中的方法不必是抽象的;abstract class類中定義抽象方法必須在具體子類中實現,所以,不能有抽象構造方法或抽象靜態方法;如果的子類沒有實現抽象父類中的所有抽象方法,那麼子類也必須定義為abstract類型。
介面(interface):可以說成是抽象類別的一種特例,由interface修飾。介面中的所有方法都必須是抽象的;介面中的方法定義預設為public abstract類型;介面中的成員變數類型預設為public static final。
兩者的文法區別:
1.抽象類別可以有構造方法,介面中不能有構造方法。
2.抽象類別中可以有普通成員變數,介面中沒有普通成員變數。
3.抽象類別中可以包含非抽象的普通方法,介面中的所有方法必須都是抽象的,不能有非抽象的普通方法。
4. 抽象類別中的抽象方法的訪問類型可以是public,protected和(預設類型,雖然eclipse下不報錯,但應該也不),但介面中的抽象方法只能是public類型的,並且預設即為public abstract類型。
5. 抽象類別中可以包含靜態方法,介面中不能包含靜態方法。
6. 抽象類別和介面中都可以包含靜態成員變數,抽象類別中的靜態成員變數的訪問類型可以任意,但介面中定義的變數只能是public static final類型,並且預設即為public static final類型。
7. 一個類可以實現多個介面,但只能繼承一個抽象類別。
兩者應用的區別:
1、Java介面和Java抽象類別最大的一個區別,就在於Java抽象類別可以提供某些方法的部分實現,而Java介面不可以(就是interface中只能定義方法,而不能有方法的實現,而在abstract class中則可以既有方法的具體實現,又有沒有具體實現的抽象方法),這大概就是Java抽象類別唯一的優點吧,但這個優點非常有用。如果向一個抽象類別裡加入一個新的具體方法時,那麼它所有的子類都一下子都得到了這個新方法,而Java介面做不到這一點,如果向一個Java介面裡加入一個 新方法,所有實現這個介面的類就無法成功通過編譯了,因為你必須讓每一個類都再實現這個方法才行,這顯然是Java介面的缺點。這個在我的另外一篇部落格mapreduce 新舊API 區別中有提到類似的問題,在新的mapreduce api中更傾向於使用抽象類別,而不是介面,因為這更容易擴充。原因就是上面劃線部分所說的。
2、一個抽象類別的實現只能由這個抽象類別的子類給出,也就是說,這個實現處在抽象類別所定義出的繼承的等級結構中,而由於Java語言的單繼承性,所以抽象類別作為類型定義工具的效能大打折扣。在這一點上,Java介面的優勢就出來了,任何一個實現了一個Java介面所規定的方法的類都可以具有這個介面的類型,而一個類可以實現任意多個Java介面,從而這個類就有了多種類型。(使用抽象類別,那麼繼承這個抽象類別的子類類型就比較單一,因為子類只能單繼承抽象類別;而子類能夠同時實現多個介面,因為類型就比較多。介面和抽象類別都可以定義對象,但是只能用他們的具體實作類別來進行執行個體化。)
3、介面是一組規則的集合,它規定了實現本介面的類或介面必須擁有的一組規則。體現了自然界“如果你是……則必須能……”的理念。
例如,在自然界中,人都能吃飯,即“如果你是人,則必須能吃飯”。那麼類比到電腦程式中,就應該有一個IPerson(習慣上,介面名由“I”開頭)介面,並有一個方法叫Eat(),然後我們規定,每一個表示“人”的類,必須實現IPerson介面,這就類比了自然界“如果你是人,則必須能吃飯”這條規則。
從這裡,我想各位也能看到些許物件導向思想的東西。物件導向思想的核心之一,就是類比真實世界,把真實世界中的事物抽象成類,整個程式靠各個類的執行個體互相通訊、互相協作完成系統功能,這非常符合真實世界的健全狀態,也是物件導向思想的精髓。
4、介面是在一定粒度視圖上同類事物的抽象表示。注意這裡我強調了在一定粒度視圖上,因為“同類事物”這個概念是相對的,它因為粒度視圖不同而不同。
例如,在我的眼裡,我是一個人,和一頭豬有本質區別,我可以接受我和我同學是同類這個說法,但絕不能接受我和一頭豬是同類。但是,如果在一個動物學家眼裡,我和豬應該是同類,因為我們都是動物,他可以認為“人”和“豬”都實現了IAnimal這個介面,而他在研究動物行為時,不會把我和豬分開對待,而會從“動物”這個較大的粒度上研究,但他會認為我和一棵樹有本質區別。
現在換了一個遺傳學家,情況又不同了,因為生物都能遺傳,所以在他眼裡,我不僅和豬沒區別,和一隻蚊子、一個細菌、一顆樹、一個蘑菇乃至一個SARS病毒都沒什麼區別,因為他會認為我們都實現了IDescendable這個介面(註:descend vi. 遺傳),即我們都是可遺傳的東西,他不會分別研究我們,而會將所有生物作為同類進行研究,在他眼裡沒有人和病毒之分,只有可遺傳的物質和不可遺傳的物質。但至少,我和一塊石頭還是有區別的。
可不幸的事情發生了,某日,地球上出現了一位偉大的人,他叫列寧,他在熟讀馬克思、恩格斯的辯證唯物主義思想巨著後,頗有心得,於是他下了一個著名的定義:所謂物質,就是能被意識所反映的客觀實在。至此,我和一塊石頭、一絲空氣、一條成語和傳輸手機訊號的電磁場已經沒什麼區別了,因為在列寧的眼裡,我們都是可以被意識所反映的客觀實在。如果列寧是一名程式員,他會這麼說:所謂物質,就是所有同時實現了“IReflectabe”和“IEsse”兩個介面的類所產生的執行個體。(註:reflect v. 反映 esse n. 客觀實在)
也許你會覺得我上面的例子像在瞎掰,但是,這正是介面得以存在的意義。物件導向思想和核心之一叫做多態性,什麼叫多態性?說白了就是在某個粒度視圖層面上對同類事物不加區別的對待而統一處理。而之所以敢這樣做,就是因為有介面的存在。像那個遺傳學家,他明白所有生物都實現了IDescendable介面,那隻要是生物,一定有Descend()這個方法,於是他就可以統一研究,而不至於分別研究每一種生物而最終累死。
最後,什麼時候使用介面和抽象類別?
看你想實現什麼功能。使用抽象類別是為了代碼的複用,而使用介面的動機是為了實現多態性。所以,如果你在為某個地方該使用介面還是抽象類別而猶豫不決時,那麼可以想想你的動機是什麼。
本文是對網友幾篇相關博文的總結。
java中抽象類別和介面有什麼區別