Java中的繼承關(guān)系與方法覆蓋
什么是繼承關(guān)系?
基于某個(gè)父類對(duì)象定義的加以拓展,從而產(chǎn)生新的子類定義,子類可以繼承父類原來(lái)的某些定義,也可以增加原來(lái)父類沒(méi)有的定義,或者覆寫(xiě)父類中的某些特性。
從面向?qū)ο蟮慕嵌壬蟻?lái)說(shuō),繼承是一種從一般到特殊的關(guān)系,是一種“ is a ”的關(guān)系,即子類是父類的拓展,是一種特殊的父類,比如狗是動(dòng)物的一種特殊情況,狗屬于動(dòng)物。
在Java語(yǔ)言當(dāng)中,存在多個(gè)類的時(shí)候,我們使用“extends”關(guān)鍵字來(lái)表示子類和父類之間的關(guān)系。
在Java語(yǔ)言當(dāng)中,類和類之間的繼承關(guān)系,只允許單繼承,不允許多繼承,也就是說(shuō)一個(gè)類A,只能有一個(gè)直接的父類,不能出現(xiàn)A類同時(shí)繼承于類B和類C,但是在Java中,允許多重繼承。
多重繼承的例子:
動(dòng)物有胎生和孿生之分,胎生動(dòng)物有老虎,老虎又分華南虎,東本虎,孟加拉虎等。
在Java中除了Object類之外,每一個(gè)類都有一個(gè)直接的父類
比如:class Student extends Person{}
我們就說(shuō)此時(shí)的Student的直接父類是Person,那么Person的父類又是誰(shuí)呢?
Object類是Java語(yǔ)言的根類(老祖宗,任何類都是Object的子類)
class Person{}等價(jià)與 class Person extend Object{}
Object類要么是一個(gè)類直接父類,要么是一個(gè)類間接父類
繼承關(guān)系的作用
(1)解決了代碼重復(fù)的問(wèn)題
(2)真正的作用,表現(xiàn)出了一個(gè)體系。
子類可以繼承哪些父類成員?
子類繼承父類之后,可以擁有父類的某一些狀態(tài)和行為(子類復(fù)用了父類的功能或狀態(tài))
子類到底繼承了父類的哪些成員(根據(jù)訪問(wèn)修飾符來(lái)判斷):
(1)如果父類中的成員使用public修飾,子類繼承;
(2)如果父類中的成員使用protected修飾,子類也繼承,即使父類和子類不在同一個(gè)包中;
(3)如果父類和子類在同一個(gè)包中,此時(shí)的子類可有繼承父類中缺省修飾符的成員;
(4)如果父類中的成員使用private修飾,子類打死都繼承不到,因?yàn)閜rivate只能在本類中訪問(wèn);
(5)父類的構(gòu)造器,子類也不能繼承,因?yàn)闃?gòu)造器必須和當(dāng)前的類名相同。
方法覆蓋(復(fù)寫(xiě)/覆寫(xiě))
子類拓展了父類,可以或得父類的部分方法和成員變量??墒钱?dāng)父類的某個(gè)方法不適合本身的特征時(shí),此時(shí)怎么辦?
如:企鵝和鴕鳥(niǎo)是鳥(niǎo)中一個(gè)特殊品種,所以企鵝/鴕鳥(niǎo)是鳥(niǎo)類的一個(gè)子類,但是鳥(niǎo)類有飛翔的功能,但是對(duì)應(yīng)于企鵝/鴕鳥(niǎo),飛翔的行為顯然不適合它。
這個(gè)時(shí)候就用到了方法覆蓋,如下代碼。
創(chuàng)建了一個(gè)子類對(duì)象Penguin ,并調(diào)用fly方法。這個(gè)過(guò)程其實(shí)是先從子類中去尋找fly方法,如果找到就執(zhí)行,若是找不到,則繼續(xù)去父類中去找。
//鳥(niǎo)類 clas Bird{ public void fly(){ System.out.println("我可以飛翔"); } } //企鵝類 class Penguin extends Bird{ // 重新定義了fly行為 public void fly(){ System.out.println("我不可以飛翔"); } }
方法覆蓋的原則(一同兩小一大):Override
一同:
(1)實(shí)例方法簽名必須相同(方法簽名=方法名+方法的參數(shù)列表)
兩?。?/strong>
(2)子類方法的返回值類型是和父類方法的返回類型相同或者其子類;
或者說(shuō),子類可以返回一個(gè)更加具體的類。如下代碼:
但是在實(shí)際開(kāi)發(fā)中,沒(méi)必要這樣做,直接使用(1)敘述的就行了
class Bird { public Object fly(){ System.out.println("fly"); return null; } } class Penguin extends Bird { public String fly(){ System.out.println("Can't fly"); return "xxx"; } }
(3)子類方法聲明拋出的異常類型和父類聲明拋出的異常類型相同或者是其子類。
子類方法聲明拋出的異常類型小于或等于父類方法聲明拋出的異常類型;
子類方法可以同時(shí)聲明拋出多個(gè)屬于父類方法聲明拋出異常類的子類(RuntimeExcption類型除外);
一大:
(4)子類方法的訪問(wèn)權(quán)限比父類方法的訪問(wèn)權(quán)限更大或相等。
class Person { public void fly(){ System.out.println("fly"); } } class Student extends Person { // 編譯報(bào)錯(cuò),子類方法的訪問(wèn)權(quán)限要比父類方法的訪問(wèn)權(quán)限更大或相等。 void fly(){ System.out.println("Can't fly"); } }
private修飾的方法不能被子類所繼承,也就不存在覆蓋的概念。
判斷是否覆蓋方法的必殺技:@Override標(biāo)簽:若方法是復(fù)寫(xiě)方法,在方法前或上貼上該標(biāo)簽,編譯通過(guò),否則,編譯出錯(cuò)。
class Person { private void fly(){ System.out.println("fly"); } } class Student extends Person { @Override public void fly(){ System.out.println("Can't fly"); } }
---------- 編譯java ----------
ExtendsDemo.java:10: 錯(cuò)誤: 方法不會(huì)覆蓋或?qū)崿F(xiàn)超類型的方法
@Override
^
1 個(gè)錯(cuò)誤輸出完成 (耗時(shí) 0 秒) - 正常終止
注意:
1. 只有方法存在覆蓋的概念,字段沒(méi)有覆蓋。
2. 方法覆蓋解決的問(wèn)題:當(dāng)父類的某一個(gè)行為不符合子類具體的特征時(shí),此時(shí)子類需要重新定義父類
方法的重載與覆蓋的區(qū)別
- 方法重載(Overload)
- 方法重寫(xiě)(Override)
二者本身沒(méi)有一點(diǎn)關(guān)系,僅僅只是名字很像
方法的重寫(xiě)
作用:
解決子類繼承父類之后,可能父類的某一個(gè)方法不再滿足子類的具體特征,此時(shí)需要重新定義子類中定義的該方法,并重寫(xiě)方法體;
規(guī)則:
1.參數(shù)列表必須完全與被重寫(xiě)方法的相同;
2.返回類型必須完全與被重寫(xiě)方法的返回類型相同;
3.訪問(wèn)權(quán)限不能比父類中被重寫(xiě)的方法的訪問(wèn)權(quán)限更低。例如:如果父類的一個(gè)方法被聲明為public,那么在子類中重寫(xiě)該方法就不能聲明為protected。
4.父類的成員方法只能被它的子類重寫(xiě)。
5.聲明為final的方法不能被重寫(xiě)。
6.聲明為static的方法不能被重寫(xiě),但是能夠被再次聲明。
7.子類和父類在同一個(gè)包中,那么子類可以重寫(xiě)父類所有方法,除了聲明為private和final的方法。
8.子類和父類不在同一個(gè)包中,那么子類只能夠重寫(xiě)父類的聲明為public和protected的非final方法。
9.重寫(xiě)的方法能夠拋出任何非強(qiáng)制異常,無(wú)論被重寫(xiě)的方法是否拋出異常。但是,重寫(xiě)的方法不能拋出新的強(qiáng)制性異常,或者比被重寫(xiě)方法聲明的更廣泛的強(qiáng)制性異常,反之則可以。
10.構(gòu)造方法不能被重寫(xiě)。
11.如果不能繼承一個(gè)方法,則不能重寫(xiě)這個(gè)方法。
重載
作用:
重載(overloading) 是在一個(gè)類里面,方法名字相同,而參數(shù)不同。返回類型可以相同也可以不同。
每個(gè)重載的方法(或者構(gòu)造函數(shù))都必須有一個(gè)獨(dú)一無(wú)二的參數(shù)類型列表。
最常用的地方就是構(gòu)造器的重載。
規(guī)則:
1.被重載的方法必須改變參數(shù)列表(參數(shù)個(gè)數(shù)或類型不一樣);
2.被重載的方法可以改變返回類型;
3.被重載的方法可以改變?cè)L問(wèn)修飾符;
4.被重載的方法可以聲明新的或更廣的檢查異常;
5.方法能夠在同一個(gè)類中或者在一個(gè)子類中被重載。
6.無(wú)法以返回值類型作為重載函數(shù)的區(qū)分標(biāo)準(zhǔn)。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java Elastic Job動(dòng)態(tài)添加任務(wù)實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了Java Elastic Job動(dòng)態(tài)添加任務(wù)實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08Java橋梁設(shè)計(jì)模式優(yōu)雅地將抽象與實(shí)現(xiàn)分離
Java橋接設(shè)計(jì)模式通過(guò)將抽象和實(shí)現(xiàn)分離,使得它們可以獨(dú)立地變化,從而實(shí)現(xiàn)更靈活的代碼結(jié)構(gòu)。它是一種優(yōu)雅的設(shè)計(jì)模式,適用于需要處理多個(gè)變化因素的復(fù)雜應(yīng)用程序2023-04-04Java 中DateUtils日期工具類的實(shí)例詳解
這篇文章主要介紹了Java 中DateUtils日期工具類的實(shí)例詳解的相關(guān)資料,有時(shí)候開(kāi)發(fā)java項(xiàng)目使用日期類型,這里介紹下日期工具類,需要的朋友可以參考下2017-08-08mybatis使用@mapkey獲取的結(jié)果的鍵(key)為null問(wèn)題
這篇文章主要介紹了mybatis使用@mapkey獲取的結(jié)果的鍵(key)為null問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06Java設(shè)計(jì)模式之模板方法模式Template Method Pattern詳解
在我們實(shí)際開(kāi)發(fā)中,如果一個(gè)方法極其復(fù)雜時(shí),如果我們將所有的邏輯寫(xiě)在一個(gè)方法中,那維護(hù)起來(lái)就很困難,要替換某些步驟時(shí)都要重新寫(xiě),這樣代碼的擴(kuò)展性就很差,當(dāng)遇到這種情況就要考慮今天的主角——模板方法模式2022-11-11導(dǎo)入maven項(xiàng)目各個(gè)注解均報(bào)錯(cuò)的解決方案
這篇文章主要介紹了導(dǎo)入maven項(xiàng)目各個(gè)注解均報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java利用happen-before規(guī)則如何實(shí)現(xiàn)共享變量的同步操作詳解
這篇文章主要給大家介紹了關(guān)于Java利用happen-before規(guī)則實(shí)現(xiàn)共享變量的同步操作的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-06-06使用Feign傳遞請(qǐng)求頭信息(Finchley版本)
這篇文章主要介紹了使用Feign傳遞請(qǐng)求頭信息(Finchley版本),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03spring mvc4中相關(guān)注解的詳細(xì)講解教程
這篇文章主要給大家介紹了關(guān)于spring mvc4中相關(guān)注解的相關(guān)資料,其中詳細(xì)介紹了關(guān)于@Controller、@RequestMapping、@RathVariable、@RequestParam及@RequestBody等等注解的相關(guān)內(nèi)容,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-06-06