程序員必備知識(shí)點(diǎn):接口和抽象類有什么區(qū)別?

2021-02-27    分類: 網(wǎng)站建設(shè)

在Java中可以用接口和抽象類來定義允許有多個(gè)實(shí)現(xiàn)的類型;不過,接口和抽象類有兩個(gè)主要的不同:

  • 抽象類允許包含某些方法的實(shí)現(xiàn),接口則不允許;【Java8中已經(jīng)提供了默認(rèn)方法】
  • 從設(shè)計(jì)層面看,為了實(shí)現(xiàn)由抽象類定義的類型,類必須定義為抽象類的子類,這就限制了它在類圖中的層次,但是接口則沒有這種層次的限制;

在實(shí)際開發(fā)中,我們應(yīng)該遵循一個(gè)原則——接口優(yōu)于抽象類,主要是由于接口有三個(gè)方面的優(yōu)勢(shì):

  • 只要實(shí)現(xiàn)新的接口,就可以給現(xiàn)有的類增加新的功能;但是一個(gè)類只能繼承自一個(gè)父類;
  • 接口非常適合用于定義mixin(混合類型)。Comparable是一個(gè)mixin接口,是因?yàn)槿魏晤愋偷膶?duì)象都可以實(shí)現(xiàn)該接口來提供對(duì)象比較的能力,跟自己的主要功能混合。
  • 接口對(duì)實(shí)現(xiàn)它的類沒有嚴(yán)格的層次要求,在設(shè)計(jì)上更靈活。

知識(shí)點(diǎn)梳理

Java中的抽象類

抽象類的設(shè)計(jì)理念介于普通的類與接口之間,抽象類的目標(biāo)是為了設(shè)計(jì)一個(gè)通用的、允許有多個(gè)實(shí)現(xiàn)的類型。

包含抽象方法的類叫做抽象類;抽象類無法實(shí)例化,如果一個(gè)類繼承了某個(gè)抽象類,并且想實(shí)例化,就需要實(shí)現(xiàn)抽象類中的所有抽象方法。

抽象類在Java中的應(yīng)用,最經(jīng)典的是“骨架模式”——和接口配合使用,讓設(shè)計(jì)同時(shí)具備抽象類和接口的優(yōu)點(diǎn)——抽象類的演變比接口的演變要容易,同時(shí)允許系統(tǒng)中的其他類不使用這個(gè)骨架實(shí)現(xiàn)類。

在“骨架模式”中,接口的作用仍然是定義類型,骨架實(shí)現(xiàn)類就是一個(gè)抽象類,負(fù)責(zé)所有與接口實(shí)現(xiàn)相關(guān)的工作。集合框架中大量應(yīng)用了“骨架模式”,例如:AbstractCollection、AbstractList、AbstractMap和AbstractSet,將一些通用的操作都放在骨架實(shí)現(xiàn)類中實(shí)現(xiàn),這樣具體的ArrayList和LinkedList就可以專注于自己的特性的實(shí)現(xiàn),避免寫重復(fù)代碼。

“骨架模式”聽起來有點(diǎn)像設(shè)計(jì)模式中的模板方法,不過二者之間還是有不一樣的:“骨架模式”的目標(biāo)是從代碼層面避免重復(fù)代碼,“模板方法”的目標(biāo)是在設(shè)計(jì)層面對(duì)某一類事情的抽象和擴(kuò)展點(diǎn)的設(shè)計(jì)。

Java中的接口

在Java中接口的語義是“is like”——任何實(shí)現(xiàn)了某個(gè)接口的類,看起來就像具備了這個(gè)接口的能力。

在Java中,接口可以用來做三個(gè)事情:

  • 類型定義;
  • 作為常量接口,保存一些常量;
  • 僅作為標(biāo)簽使用。

不過在《Effective Java》的第19條指出,接口應(yīng)該只用于定義類型。

在Java8之前,接口中只能出現(xiàn)方法的聲明,不能出現(xiàn)方法的實(shí)現(xiàn)。Java 8對(duì)接口的能力做了增強(qiáng):

  1. 接口中可以有default method;
  2. 接口中可以有static method;
  3. 提供了FunctionInterface這個(gè)概念。

1.

Java 8中引入default method最主要的動(dòng)機(jī)是:在Java 8中要支持lambda表達(dá)式,這就需要對(duì)原來JDK中的很多接口做修改,但是由于接口的特性(其實(shí)現(xiàn)類必須實(shí)現(xiàn)接口中聲明的所有方法)的限制,如果直接修改,就會(huì)導(dǎo)致現(xiàn)有的Java應(yīng)用在升級(jí)到Java 8的時(shí)候全部編譯報(bào)錯(cuò)——這是不可接受的。

在實(shí)際開發(fā)中,對(duì)于default method的使用你可以注意幾個(gè)點(diǎn):

  • 可以按照需要擴(kuò)展接口,而不需要擔(dān)心影響已有的實(shí)現(xiàn)類;
  • 使得接口和抽象類幾乎沒有區(qū)別了,后面可以放心得使用接口,同時(shí)能利用default method獲得抽象類的優(yōu)點(diǎn);
  • 可以省去很多為某個(gè)接口提供的工具類了,這些工具類中的方法可以放在接口中實(shí)現(xiàn),例如Collections這個(gè)類中的方法可以都放在Collection接口中;

2

跟default method類似,static method也可以在接口中實(shí)現(xiàn),但是你在使用過程中不能覆蓋static method,因此,如果有些方法你不希望被具體的實(shí)現(xiàn)類破壞,就可以將之聲明為static method。

在實(shí)際開發(fā)中,對(duì)于static method的使用你可以注意幾個(gè)點(diǎn):

  • static method是屬于某個(gè)接口的,不是屬于某個(gè)對(duì)象的;
  • static method比較適合用于實(shí)現(xiàn)接口相關(guān)的工具方法,例如空值檢查、集合排序等等;
  • 將Collections中的方法移動(dòng)到Collection接口中,方便開發(fā)者找到對(duì)應(yīng)的方法使用,這種方法也比較適合使用static method。

3

為了支持lambda表達(dá)式,Java 8引入了一個(gè)新的注解:

@FunctionalInterface //方法注解

如果某個(gè)接口被這個(gè)注解修飾,這個(gè)接口就會(huì)被稱為函數(shù)式接口。函數(shù)式接口注解不是必須的,但是是一種好的實(shí)踐。

如果一個(gè)接口符合"函數(shù)式接口"定義,那么加不加該注解都沒有影響。加上該注解能夠更好地讓編譯器進(jìn)行檢查。如果編寫的不是函數(shù)式接口,但是加上了@FunctionInterface,那么編譯器會(huì)報(bào)錯(cuò)。。

參考資料

  1. https://www.journaldev.com/2752/java-8-interface-changes-static-method-default-method
  2. 《Effective Java(中文版)第二版》
  3. 《Java編程思想》

網(wǎng)頁標(biāo)題:程序員必備知識(shí)點(diǎn):接口和抽象類有什么區(qū)別?
網(wǎng)頁地址:http://www.muchs.cn/news5/103205.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、自適應(yīng)網(wǎng)站網(wǎng)站改版、企業(yè)網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管