- Java程序員面試筆試寶典(第2版)
- 何昊等編著
- 1675字
- 2022-06-17 16:00:43
1.8 abstract class(抽象類)與interface(接口)的異同
如果一個類中包含抽象方法,那么這個類就是抽象類。在Java語言中,可以通過把類或者類中的某些方法聲明為abstract(abstract只能用來修飾類或者方法,不能用來修飾屬性)來表示一個類是抽象類。只要包含一個抽象方法的類就必須被聲明為抽象類,抽象類可以僅聲明方法的存在而不去實現(xiàn)它,被聲明為抽象的方法不能包含方法體。在實現(xiàn)時,必須包含相同的或者更低的訪問級別(public->protected->private)。抽象類在使用的過程中不能被實例化,但是可以創(chuàng)建一個對象使其指向具體子類的一個實例。抽象類的子類為父類中所有的抽象方法提供具體的實現(xiàn),否則它們也是抽象類。
接口就是指一個方法的集合,在Java語言中,接口是通過關(guān)鍵字interface來實現(xiàn)的。在Java8之前,接口中既可以定義方法也可以定義變量,其中變量必須是public、static、final的,而方法必須是public、abstract的。由于這些修飾符都是默認的,所以在Java8之前,下面的寫法都是等價的。

從Java8開始,通過使用關(guān)鍵字default可以給接口中的方法添加默認實現(xiàn),此外,接口中還可以定義靜態(tài)方法,示例代碼如下所示:

那么,為什么要引入接口中方法的默認實現(xiàn)呢?
其實,這樣做的最重要的一個目的就是實現(xiàn)接口升級。在原有的設(shè)計中,如果想要升級接口,例如給接口中添加一個新的方法,那么會導致所有實現(xiàn)這個接口的類都需要被修改,這給Java語言已有的一些框架進行升級帶來了很大的麻煩。如果接口能支持默認方法的實現(xiàn),那么可以給這些類庫的升級帶來許多便利。例如,為了支持Lambda表達式,Collection中引入了foreach方法,可以通過這個語法增加默認的實現(xiàn),從而降低了對這個接口進行升級的代價,不需要對所有實現(xiàn)這個接口的類進行修改。
在Java8之前,實現(xiàn)接口的非抽象類必須要實現(xiàn)接口中的方法,在Java8中引入接口中方法的默認實現(xiàn)后,實現(xiàn)接口的類也可以不實現(xiàn)接口中的方法,例如:

接口中的靜態(tài)方法只能通過接口名來調(diào)用,不可以通過實現(xiàn)類的類名或者實現(xiàn)類的對象來調(diào)用。而default方法則只能通過接口實現(xiàn)類的對象來調(diào)用。示例代碼如下:

在Java中由于不支持多重繼承,也就是說一個類只能繼承一個父類,不能同時繼承多個父類,但是一個類可以實現(xiàn)多個接口。因此經(jīng)常通過實現(xiàn)多個接口的方式來實現(xiàn)多重繼承的目的。那么如果多個接口中存在同名的static和default方法會有什么樣的問題呢?靜態(tài)方法并不會導致歧義的出現(xiàn),因為靜態(tài)方法只能通過接口名來調(diào)用;對于default方法來說,在這種情況下,這個類必須要重寫接口中的這個方法,否則無法確定到底使用哪個接口中默認的實現(xiàn)。
從上面的介紹可以看出接口與抽象類有很多相似的地方,那么它們有哪些不同點呢?
(1)抽象類
1)抽象類只能被繼承(用extends)。并且一個類只能繼承一個抽象類。
2)抽象類強調(diào)所屬關(guān)系,其設(shè)計理念為is-a關(guān)系。
3)抽象類更傾向于充當公共類的角色,不適用于日后重新對里面的代碼進行修改。
4)除了抽象方法之外,抽象類還可以包含具體數(shù)據(jù)和具體方法(可以有方法的實現(xiàn))。
5)抽象類不能被實例化,如果子類實現(xiàn)了所有的抽象方法,那么子類就可以被實例化了。如果子類只實現(xiàn)了部分抽象方法,那么子類還是抽象類,不能被實例化。
(2)接口
1)接口需要實現(xiàn)(用implements),一個類可以實現(xiàn)多個接口,因此使用接口可以間接地實現(xiàn)多重繼承的目的。
2)接口強調(diào)特定功能的實現(xiàn),其設(shè)計理念是has-a關(guān)系。
3)接口被運用于實現(xiàn)比較常用的功能,便于日后維護或者添加刪除方法。
4)接口不是類,而是對類的一組需求描述,這些類要遵從接口描述的統(tǒng)一格式進行定義。
5)接口中的所有方法都是public的,因此,在實現(xiàn)接口的類中,必須把方法聲明成public,因為類中默認的訪問屬性是包可見的,而不是public,這就相當于在子類中降低了方法的可見性,會導致編譯錯誤。
總之,接口是一種特殊形式的抽象類,使用接口完全有可能實現(xiàn)與抽象類相同的操作,但一般而言,抽象類多用于在同類事物中有無法具體描述的方法的場景,所以當子類和父類之間存在有邏輯上的層次結(jié)構(gòu)時,推薦使用抽象類,而接口多用于不同類之間,定義不同類之間的通信規(guī)則,所以當希望支持差別較大的兩個或者更多對象之間的特定交互行為時,應該使用接口。
此外,接口可以繼承接口,抽象類可以實現(xiàn)接口,抽象類也可以繼承具體類。抽象類也可以有靜態(tài)的main方法。
- Bootstrap Site Blueprints Volume II
- Vue.js 3.x從入門到精通(視頻教學版)
- AngularJS Web Application Development Blueprints
- 營銷數(shù)據(jù)科學:用R和Python進行預測分析的建模技術(shù)
- Groovy for Domain:specific Languages(Second Edition)
- Internet of Things with Intel Galileo
- 3D少兒游戲編程(原書第2版)
- Scala謎題
- Gradle for Android
- Python之光:Python編程入門與實戰(zhàn)
- Unity 3D腳本編程:使用C#語言開發(fā)跨平臺游戲
- 區(qū)塊鏈架構(gòu)之美:從比特幣、以太坊、超級賬本看區(qū)塊鏈架構(gòu)設(shè)計
- RocketMQ實戰(zhàn)與原理解析
- Python Machine Learning Blueprints:Intuitive data projects you can relate to
- Mobile Forensics:Advanced Investigative Strategies