JAVA 的繼承機(jī)制是一種復(fù)用類(lèi)的技術(shù),從原理上來(lái)說(shuō),是更好的使用了組合技術(shù),因此要理解繼承,首先需要了解類(lèi)的組合技術(shù)是如何實(shí)現(xiàn)類(lèi)的復(fù)用的。
使用組合技術(shù)復(fù)用類(lèi) 假設(shè)現(xiàn)在的需求是要?jiǎng)?chuàng)建一個(gè)具有基本類(lèi)型,String 類(lèi)型以及一個(gè)其他非基本類(lèi)型的對(duì)象。該如何處理呢?
對(duì)于基本類(lèi)型的變量,在新類(lèi)中成員變量處直接定義即可,但對(duì)于非基本類(lèi)型變量,不僅需要在類(lèi)中聲明其引用,并且還需要手動(dòng)初始化這個(gè)對(duì)象。
這里需要注意的是,編譯器并不會(huì)默認(rèn)將所有的引用都創(chuàng)建對(duì)象,因?yàn)檫@樣的話(huà)在很多情況下會(huì)增加不必要的負(fù)擔(dān),因此,在合適的時(shí)機(jī)初始化合適的對(duì)象,可以通過(guò)以下幾個(gè)位置做初始化操作:
在定義對(duì)象的地方,先于構(gòu)造方法執(zhí)行。在構(gòu)造方法中。在正要使用之前,這個(gè)被稱(chēng)為惰性初始化。使用實(shí)例初始化。
繼承 Java 中的繼承由 extend 關(guān)鍵字實(shí)現(xiàn),組合的語(yǔ)法比較平實(shí),而繼承是一種特殊的語(yǔ)法。當(dāng)一個(gè)類(lèi)繼承自另一個(gè)類(lèi)時(shí),那么這個(gè)類(lèi)就可以擁有另一個(gè)類(lèi)的域和方法。
上面的代碼中,展示了繼承語(yǔ)法中的一些特性:
子類(lèi)可以直接使用父類(lèi)中公共的方法和成員變量(通常為了保護(hù)數(shù)據(jù)域,成員變量均為私有) 子類(lèi)中可以覆蓋父類(lèi)中的方法,也就是子類(lèi)重寫(xiě)了父類(lèi)的方法,此時(shí)若還需要調(diào)用被覆蓋的父類(lèi)的方法,則需要用到 super 來(lái)指定是調(diào)用父類(lèi)中的方法。子類(lèi)中可以自定義父類(lèi)中沒(méi)有的方法。可以發(fā)現(xiàn)上面兩個(gè)類(lèi)中均有 main 方法,命令行中調(diào)用的哪個(gè)類(lèi)就執(zhí)行哪個(gè)類(lèi)的 main 方法,例如:java Deter。繼承語(yǔ)法的原理 接下來(lái)我們將通過(guò)創(chuàng)建子類(lèi)對(duì)象來(lái)分析繼承語(yǔ)法在我們看不到的地方做了什么樣的操作。
可以先思考一下,如何理解使用子類(lèi)創(chuàng)建的對(duì)象呢,首先這個(gè)對(duì)象中包含子類(lèi)的所有信息,但是也包含父類(lèi)的所有公共的信息。
下面來(lái)看一段代碼,觀察一下子類(lèi)在創(chuàng)建對(duì)象初始化的時(shí)候,會(huì)不會(huì)用到父類(lèi)相關(guān)的方法。
通過(guò)觀察代碼可以發(fā)現(xiàn),在實(shí)例化Cartoon時(shí),事實(shí)上是從最頂層的父類(lèi)開(kāi)始向下逐個(gè)實(shí)例化,也就是最終實(shí)例化了三個(gè)對(duì)象。編譯器會(huì)默認(rèn)在子類(lèi)的構(gòu)造方法中增加調(diào)用父類(lèi)默認(rèn)構(gòu)造方法的代碼。
因此,繼承可以理解為編譯器幫我們完成了類(lèi)的特殊組合技術(shù),即在子類(lèi)中存在一個(gè)父類(lèi)的對(duì)象,使得我們可以用子類(lèi)對(duì)象調(diào)用父類(lèi)的方法。而在開(kāi)發(fā)者看來(lái)只不過(guò)是使用了一個(gè)關(guān)鍵字。
注意:雖然繼承很接近組合技術(shù),但是繼承擁有其他更多的區(qū)別于組合的特性,例如父類(lèi)的對(duì)象我們是不可見(jiàn)的,對(duì)于父類(lèi)中的方法也做了相應(yīng)的權(quán)限校驗(yàn)等。






