溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java內(nèi)功心法,深入解析面向?qū)ο?/h1>
發(fā)布時(shí)間:2020-07-16 10:15:45 來源:網(wǎng)絡(luò) 閱讀:439 作者:Java筆記丶 欄目:編程語言

什么是對(duì)象

對(duì)象是系統(tǒng)中用來描述客觀事物的一個(gè)實(shí)體,它是構(gòu)成系統(tǒng)的一個(gè)基本單位。一個(gè)對(duì)象由一組屬性和對(duì)這組屬性進(jìn)行操作的一組服務(wù)組成。

類的實(shí)例化可生成對(duì)象,一個(gè)對(duì)象的生命周期包括三個(gè)階段:生成、使用、消除。

當(dāng)不存在對(duì)一個(gè)對(duì)象的引用時(shí),該對(duì)象成為一個(gè)無用對(duì)象。Java的垃圾收集器自動(dòng)掃描對(duì)象的動(dòng)態(tài)內(nèi)存區(qū),把沒有引用的對(duì)象作為垃圾收集起來并釋放。當(dāng)系統(tǒng)內(nèi)存用盡或調(diào)用System.gc()要求垃圾回收時(shí),垃圾回收程與系統(tǒng)同步運(yùn)行。

面向?qū)ο蟮奶卣?/h3>

封裝,繼承和多態(tài)。

  • 封裝:面向?qū)ο笞罨A(chǔ)的一個(gè)特性,封裝性,是指隱藏對(duì)象的屬性和現(xiàn)實(shí)細(xì)節(jié),僅對(duì)外提供公共訪問方式。

封裝的原則:將不需要對(duì)外提供的內(nèi)容都隱藏(設(shè)置訪問修飾符為“private”)起來。把屬性都隱藏,僅提供公共方法對(duì)其訪問,可以在訪問方式中加入邏輯判斷等語句。
  • 繼承:繼承是從已有類得到繼承信息創(chuàng)建新類的過程。提供繼承信息的類被稱為父類(超類、基類);得到繼承信息的類被稱為子類(派生類)。

  • 多態(tài):多態(tài)性是指允許不同子類型的對(duì)象對(duì)同一消息作出不同的響應(yīng)。簡單的說就是用同樣的對(duì)象引用調(diào)用同樣的方法但是做了不同的事情。

多態(tài)性分為編譯時(shí)的多態(tài)性和運(yùn)行時(shí)的多態(tài)性。
運(yùn)行時(shí)的多態(tài)是面向?qū)ο笞罹璧臇|西,要實(shí)現(xiàn)多態(tài)需要做兩件事:
1). 方法重寫(子類繼承父類并重寫父類中已有的或抽象的方法)
2). 對(duì)象造型(用父類型引用引用子類型對(duì)象,這樣同樣的引用調(diào)用同樣的方法就會(huì)根據(jù)子類對(duì)象的不同而表現(xiàn)出不同的行為)。

什么是類

類是具有相同屬性和方法的一組對(duì)象的集合,它為屬于該類的所有對(duì)象提供了統(tǒng)一的抽象描述,其內(nèi)部包括屬性和方法兩個(gè)主要部分。在面向?qū)ο蟮木幊陶Z言中,類是一個(gè)獨(dú)立的程序單位,它應(yīng)該有一個(gè)類名并包括屬性和方法兩個(gè)主要部分。

Java中的類實(shí)現(xiàn)包括兩個(gè)部分:類聲明和類體。

多態(tài)的好處

多態(tài)的定義:指允許不同類的對(duì)象對(duì)同一消息做出響應(yīng)。即同一消息可以根據(jù)發(fā)送對(duì)象的不同而采用多種不同的行為方式。

主要有以下優(yōu)點(diǎn):

  • 可替換性:多態(tài)對(duì)已存在代碼具有可替換性.

  • 可擴(kuò)充性:增加新的子類不影響已經(jīng)存在的類結(jié)構(gòu).

  • 接口性:多態(tài)是超類通過方法簽名,向子類提供一個(gè)公共接口,由子類來完善或者重寫它來實(shí)現(xiàn)的.

  • 靈活性:它在應(yīng)用中體現(xiàn)了靈活多樣的操作,提高了使用效率

  • 簡化性:多態(tài)簡化對(duì)應(yīng)用軟件的代碼編寫和修改過程,尤其在處理大量對(duì)象的運(yùn)算和操作時(shí),這個(gè)特點(diǎn)尤為突出和重要

代碼中如何實(shí)現(xiàn)多態(tài)

實(shí)現(xiàn)多態(tài)主要有以下三種方式:

  • 接口實(shí)現(xiàn)

  • 繼承父類重寫方法

  • 同一類中進(jìn)行方法重載

虛擬機(jī)是如何實(shí)現(xiàn)多態(tài)的

動(dòng)態(tài)綁定技術(shù)(dynamic binding),執(zhí)行期間判斷所引用對(duì)象的實(shí)際類型,根據(jù)實(shí)際類型調(diào)用對(duì)應(yīng)的方法.

重載(Overload)和重寫(Override)的區(qū)別。重載的方法能否根據(jù)返回類型進(jìn)行區(qū)分?

方法的重載和重寫都是實(shí)現(xiàn)多態(tài)的方式,區(qū)別在于前者實(shí)現(xiàn)的是編譯時(shí)的多態(tài)性,而后者實(shí)現(xiàn)的是運(yùn)行時(shí)的多態(tài)性。

  • 重載發(fā)生在一個(gè)類中,同名的方法如果有不同的參數(shù)列表(參數(shù)類型不同、參數(shù)個(gè)數(shù)不同或者二者都不同)則視為重載;

  • 重寫發(fā)生在子類與父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的返回類型,比父類被重寫方法更好訪問,不能比父類被重寫方法聲明更多的異常(里氏代換原則)。重載對(duì)返回類型沒有特殊的要求。

構(gòu)造器不能被繼承,因此不能被重寫,但可以被重載。

父類的靜態(tài)方法不能被子類重寫。重寫只適用于實(shí)例方法,不能用于靜態(tài)方法,而子類當(dāng)中含有和父類相同簽名的靜態(tài)方法,我們一般稱之為隱藏,調(diào)用的方法為定義的類所有的靜態(tài)方法。

構(gòu)造器(constructor)是否可被重寫(override)?

構(gòu)造器不能被繼承,因此不能被重寫,但可以被重載。

接口的意義

接口的意義用四個(gè)詞就可以概括:規(guī)范,擴(kuò)展,回調(diào)和安全。

抽象類的意義

抽象類的意義可以用三句話來概括:

  • 為其他子類提供一個(gè)公共的類型

  • 封裝子類中重復(fù)定義的內(nèi)容

  • 定義抽象方法,子類雖然有不同的實(shí)現(xiàn),但是定義是一致的

抽象類和接口有什么區(qū)別

抽象類和接口都不能夠?qū)嵗?,但可以定義抽象類和接口類型的引用。一個(gè)類如果繼承了某個(gè)抽象類或者實(shí)現(xiàn)了某個(gè)接口都需要對(duì)其中的抽象方法全部進(jìn)行實(shí)現(xiàn),否則該類仍然需要被聲明為抽象類。接口比抽象類更加抽象,因?yàn)槌橄箢愔锌梢远x構(gòu)造器,可以有抽象方法和具體方法,而接口中不能定義構(gòu)造器而且其中的方法全部都是抽象方法。抽象類中的成員可以是private、默認(rèn)、protected、public的,而接口中的成員全都是public的。抽象類中可以定義成員變量,而接口中定義的成員變量實(shí)際上都是常量。有抽象方法的類必須被聲明為抽象類,而抽象類未必要有抽象方法。

訪問修飾符public,private,protected,以及不寫(默認(rèn))時(shí)的區(qū)別

修飾符當(dāng)前類同包子類其他包public√√√√protected√√√×default√√××private√×××

類的成員不寫訪問修飾時(shí)默認(rèn)為default。默認(rèn)對(duì)于同一個(gè)包中的其他類相當(dāng)于公開(public),對(duì)于不是同一個(gè)包中的其他類相當(dāng)于私有(private)。受保護(hù)(protected)對(duì)子類相當(dāng)于公開,對(duì)不是同一包中的沒有父子關(guān)系的類相當(dāng)于私有。Java中,外部類的修飾符只能是public或默認(rèn),類的成員(包括內(nèi)部類)的修飾符可以是以上四種。

簡述一下面向?qū)ο蟮摹绷瓌t一法則”。

  • 單一職責(zé)原則:一個(gè)類只做它該做的事情。

單一職責(zé)原則想表達(dá)的就是”高內(nèi)聚”,寫代碼最終極的原則只有六個(gè)字”高內(nèi)聚、低耦合”。所謂的高內(nèi)聚就是一個(gè)代碼模塊只完成一項(xiàng)功能,在面向?qū)ο笾?,如果只讓一個(gè)類完成它該做的事,而不涉及與它無關(guān)的領(lǐng)域就是踐行了高內(nèi)聚的原則,這個(gè)類就只有單一職責(zé)。我們都知道一句話叫”因?yàn)閷Wⅲ詫I(yè)”,一個(gè)對(duì)象如果承擔(dān)太多的職責(zé),那么注定它什么都做不好。一個(gè)好的軟件系統(tǒng),它里面的每個(gè)功能模塊也應(yīng)該是可以輕易的拿到其他系統(tǒng)中使用的,這樣才能實(shí)現(xiàn)軟件復(fù)用的目標(biāo)。

  • 開閉原則:軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。

在理想的狀態(tài)下,當(dāng)我們需要為一個(gè)軟件系統(tǒng)增加新功能時(shí),只需要從原來的系統(tǒng)派生出一些新類就可以,不需要修改原來的任何一行代碼。要做到開閉有兩個(gè)要點(diǎn):

1)抽象是關(guān)鍵,一個(gè)系統(tǒng)中如果沒有抽象類或接口系統(tǒng)就沒有擴(kuò)展點(diǎn);

2)封裝可變性,將系統(tǒng)中的各種可變因素封裝到一個(gè)繼承結(jié)構(gòu)中,如果多個(gè)可變因素混雜在一起,系統(tǒng)將變得復(fù)雜而換亂,如果不清楚如何封裝可變性,可以參考《設(shè)計(jì)模式精解》一書中對(duì)橋梁模式的講解的章節(jié)。

  • 依賴倒轉(zhuǎn)原則:面向接口編程。

該原則說得直白和具體一些就是聲明方法的參數(shù)類型、方法的返回類型、變量的引用類型時(shí),盡可能使用抽象類型而不用具體類型,因?yàn)槌橄箢愋涂梢员凰娜魏我粋€(gè)子類型所替代,請(qǐng)參考下面的里氏替換原則。

  • 里氏替換原則:任何時(shí)候都可以用子類型替換掉父類型。

關(guān)于里氏替換原則的描述,Barbara Liskov女士的描述比這個(gè)要復(fù)雜得多,但簡單的說就是能用父類型的地方就一定能使用子類型。里氏替換原則可以檢查繼承關(guān)系是否合理,如果一個(gè)繼承關(guān)系違背了里氏替換原則,那么這個(gè)繼承關(guān)系一定是錯(cuò)誤的,需要對(duì)代碼進(jìn)行重構(gòu)。例如讓貓繼承狗,或者狗繼承貓,又或者讓正方形繼承長方形都是錯(cuò)誤的繼承關(guān)系,因?yàn)槟愫苋菀渍业竭`反里氏替換原則的場(chǎng)景。需要注意的是:子類一定是增加父類的能力而不是減少父類的能力,因?yàn)樽宇惐雀割惖哪芰Ω?,把能力多的?duì)象當(dāng)成能力少的對(duì)象來用當(dāng)然沒有任何問題。

  • 接口隔離原則:接口要小而專,絕不能大而全。

臃腫的接口是對(duì)接口的污染,既然接口表示能力,那么一個(gè)接口只應(yīng)該描述一種能力,接口也應(yīng)該是高度內(nèi)聚的。例如,琴棋書畫就應(yīng)該分別設(shè)計(jì)為四個(gè)接口,而不應(yīng)設(shè)計(jì)成一個(gè)接口中的四個(gè)方法,因?yàn)槿绻O(shè)計(jì)成一個(gè)接口中的四個(gè)方法,那么這個(gè)接口很難用,畢竟琴棋書畫四樣都精通的人還是少數(shù),而如果設(shè)計(jì)成四個(gè)接口,會(huì)幾項(xiàng)就實(shí)現(xiàn)幾個(gè)接口,這樣的話每個(gè)接口被復(fù)用的可能性是很高的。Java中的接口代表能力、代表約定、代表角色,能否正確的使用接口一定是編程水平高低的重要標(biāo)識(shí)。

  • 合成聚合復(fù)用原則:優(yōu)先使用聚合或合成關(guān)系復(fù)用代碼。

通過繼承來復(fù)用代碼是面向?qū)ο蟪绦蛟O(shè)計(jì)中被濫用得最多的東西,因?yàn)樗械慕炭茣紵o一例外的對(duì)繼承進(jìn)行了鼓吹從而誤導(dǎo)了初學(xué)者,類與類之間簡單的說有三種關(guān)系,Is-A關(guān)系、Has-A關(guān)系、Use-A關(guān)系,分別代表繼承、關(guān)聯(lián)和依賴。

其中,關(guān)聯(lián)關(guān)系根據(jù)其關(guān)聯(lián)的強(qiáng)度又可以進(jìn)一步劃分為關(guān)聯(lián)、聚合和合成,但說白了都是Has-A關(guān)系,合成聚合復(fù)用原則想表達(dá)的是優(yōu)先考慮Has-A關(guān)系而不是Is-A關(guān)系復(fù)用代碼,原因嘛可以自己從百度上找到一萬個(gè)理由,需要說明的是,即使在Java的API中也有不少濫用繼承的例子,例如Properties類繼承了Hashtable類,Stack類繼承了Vector類,這些繼承明顯就是錯(cuò)誤的,更好的做法是在Properties類中放置一個(gè)Hashtable類型的成員并且將其鍵和值都設(shè)置為字符串來存儲(chǔ)數(shù)據(jù),而Stack類的設(shè)計(jì)也應(yīng)該是在Stack類中放一個(gè)Vector對(duì)象來存儲(chǔ)數(shù)據(jù)。記住:任何時(shí)候都不要繼承工具類,工具是可以擁有并可以使用的,而不是拿來繼承的。

  • 迪米特法則:迪米特法則又叫最少知識(shí)原則,一個(gè)對(duì)象應(yīng)當(dāng)對(duì)其他對(duì)象有盡可能少的了解。

迪米特法則簡單的說就是如何做到”低耦合”,門面模式和調(diào)停者模式就是對(duì)迪米特法則的踐行。對(duì)于門面模式可以舉一個(gè)簡單的例子,你去一家公司洽談業(yè)務(wù),你不需要了解這個(gè)公司內(nèi)部是如何運(yùn)作的,你甚至可以對(duì)這個(gè)公司一無所知,去的時(shí)候只需要找到公司入口處的前臺(tái)美女,告訴她們你要做什么,她們會(huì)找到合適的人跟你接洽,前臺(tái)的美女就是公司這個(gè)系統(tǒng)的門面。

再復(fù)雜的系統(tǒng)都可以為用戶提供一個(gè)簡單的門面,Java Web開發(fā)中作為前端控制器的Servlet或Filter不就是一個(gè)門面嗎,瀏覽器對(duì)服務(wù)器的運(yùn)作方式一無所知,但是通過前端控制器就能夠根據(jù)你的請(qǐng)求得到相應(yīng)的服務(wù)。

調(diào)停者模式也可以舉一個(gè)簡單的例子來說明,例如一臺(tái)計(jì)算機(jī),CPU、內(nèi)存、硬盤、顯卡、聲卡各種設(shè)備需要相互配合才能很好的工作,但是如果這些東西都直接連接到一起,計(jì)算機(jī)的布線將異常復(fù)雜,在這種情況下,主板作為一個(gè)調(diào)停者的身份出現(xiàn),它將各個(gè)設(shè)備連接在一起而不需要每個(gè)設(shè)備之間直接交換數(shù)據(jù),這樣就減小了系統(tǒng)的耦合度和復(fù)雜度。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI