天天看點

盤一盤Java中的abstract和interface(備戰2022春招或暑期實習,每天進步一點點,打卡100天,Day7)

  備戰2022春招或暑期實習,祝大家每天進步億點點!Day7

本篇總結的是 《Java中的abstract和interface》,後續會每日更新~

關于《Redis入門到精通》、《并發程式設計》等知識點可以參考我的往期部落格:《Redis從入門到精通》系列 《并發程式設計》系列

相信自己,越活越堅強,活着就該逢山開路,遇水架橋!生活,你給我壓力,我還你奇迹!

盤一盤Java中的abstract和interface(備戰2022春招或暑期實習,每天進步一點點,打卡100天,Day7)

1、簡介

abstract和interface關鍵字在Java中随處可見,它是Java三大特性封裝、繼承、多态特性的實作重要支柱之一。interface關鍵字用于定義接口抽象,其本質上是用于定義類型、定義類所具有的能力。但是新手往往錯誤的使用了abstract和interface,小捌其實也一樣犯錯誤,這篇文章我們盤一盤interface接口和abstract抽象類的使用。

文章開始前建議帶着兩個疑問閱讀:

abstract和interface有什麼差別?

abstract和interface應該怎麼選?

2、準則

定義接口的時候,有一些準則可以參考,根據這些準則可以更好的确定自己應不應該定義接口、或者是否有其他更好的代替方案。(注意小捌說的點不是絕對正确的,實際開發過程中要具體分析,有不對的可以互相交流。)

2.1 接口優先于抽象類

小捌這裡用JDK的源碼HashMap的繼承體系來說明接口優先于抽象類這一點。

HashMap繼承體系類圖結構:

盤一盤Java中的abstract和interface(備戰2022春招或暑期實習,每天進步一點點,打卡100天,Day7)

可以看到HashMap繼承了AbstractMap抽象類實作了Map接口,但為什麼說接口優先于抽象類呢?這些因為Java是單繼承多實作,HashMap繼承了AbstractMap抽象類之後就無法繼承其他類了,如果是接口就沒有這個限制,比如HashMap還需要提供序列化和克隆的功能,HashMap就可以實作三個接口Map, Cloneable, Serializable。

既然這樣為什麼HashMap還要去繼承AbstractMap抽象類呢?

這是因為在JDK源碼設計中,Map結構JDK需要提供部分方法的預設實作,是以JDK的作者們單獨拉取了一個抽象類來實作這些方法;盡管Java8 Oracle嘗試在接口中提供靜态方法和普通方法,但是小捌認為沒有到一定的需求程度,盡量、甚至完全不應該将方法實作定義在接口中。

abstract和interface有什麼差別呢?

其實在Java8之後差別在不斷的縮小,但是總體上來說還是兩個完全不同的概念:

抽象類abstract的特點:

抽象方法和抽象類都必須被abstract關鍵字修飾

一個類中有抽象方法,那麼這個類一定是抽象類

抽象類中不一定有抽象方法

抽象類中可以存在構造方法

抽象類中可以存在普通屬性、方法、靜态屬性和靜态方法

抽象類的方法必須在子類中實作,否則子類也需要定義為抽象類

抽象類不可以用new建立對象,因為調用抽象方法沒有實作就沒有意義

接口interface的特點:

接口中的方法,都被public來修飾

接口中沒有構造方法,不能執行個體化接口對象

接口中隻有常量,如果定義變量,則預設加上public static final

使用接口可以實作多繼承

接口中隻有方法的聲明,沒有方法體(适用于Java8之前,當我沒說,但是很多人都是這麼認為的,這種錯誤的認為往往能正确的設計代碼)

接口中可以聲明靜态方法,必須是public修飾(預設),靜态方法無法被子類重寫

接口中可以聲明普通方法,必須是default修飾

盤一盤Java中的abstract和interface(備戰2022春招或暑期實習,每天進步一點點,打卡100天,Day7)

總結:

在整個抽象實作體系中,必須提供一些方法的預設實作,可以使用抽象類(因為非常不建議在接口中直接實作某些方法)

如果不需要提供預設實作,且需要實作多繼承的功能就使用接口

2.2 接口中不應該實作方法

接口無處不在,接口作為類體系結構的最頂層,接口提供的一切限制和規範都是直接影響下層實作類。是以不建議在接口中實作具體的方法,盡管Java8之後的接口定義可以提供靜态方法實作和普通方法實作,但是這種實作方式有很大的風險,除非你的接口設計真的很完美,完美到能對所有的實作類都負責任的說你的邏輯永遠不會變。要不然接口的具體實作方法邏輯修改後,下面那些使用了該方法的類都得遭殃。

是以接口盡可能的隻用來定義類型、定義類所具有的能力。如果一定要定義實作,可以考慮使用抽象類來定義。

2.3 接口不應該用于導出常量

由于接口中定義常量非常友善,是以有一些小夥伴會使用接口直接作為常量導出類,比如如下這種方式:

盤一盤Java中的abstract和interface(備戰2022春招或暑期實習,每天進步一點點,打卡100天,Day7)