细品java封装继承多态
目錄:
1.封裝
2.繼承
3.多態(tài)
1.封裝
封裝的作用:封裝把一個(gè)對(duì)象的屬性私有化,同時(shí)提供一些可以被外界訪問的屬性的方法,如果屬性不想被外界訪問,我們大可不必提供方法給外界訪問。但是如果一個(gè)類沒有提供給外界訪問的方法,那么這個(gè)類也沒有什么意義了。
說成大白話就是防止別人更改你的變量
(2)訪問修飾符:
一般修飾類的話只能是默認(rèn)的default和public
1.private : 在同一類內(nèi)可見。使用對(duì)象:變量、方法。 注意:不能修飾類外部類(可以修飾內(nèi)部類)
2.default (即缺省,什么也不寫,不使用任何關(guān)鍵字): 在同一包內(nèi)可見,不使用任何修飾符。使用對(duì)象類、接口、變量、方法。
3.protected : 對(duì)同一包內(nèi)的類和所有子類可見。使用對(duì)象:變量、方法。 注意:不能修飾類外部類(可以修飾內(nèi)部類)
4.public : 對(duì)所有類可見。使用對(duì)象:類、接口、變量、方法
2.繼承
(1)繼承的定義
繼承:就是子類繼承父類的屬性和行為,使得子類對(duì)象具有與父類相同的屬性、相同的行為。子類可以直接訪問父類中的非私有的屬性和行為。
這里再聲明一點(diǎn),父類又稱為超類或者基類。而子類又稱為派生類,而且java只支持單繼承不支持多繼承這點(diǎn)很重要
(2)繼承的優(yōu)點(diǎn):
1.提高代碼的復(fù)用性。
2.類與類之間產(chǎn)生關(guān)系,為多態(tài)做了完美的鋪墊
(3)繼承格式
class A extends B{ }(4)繼承后的成員變量重名問題
可以使用super和this來分別調(diào)用
如圖:
這里注意一點(diǎn)不要在主函數(shù)里邊直接用super.+方法名可能會(huì)報(bào)錯(cuò),因?yàn)閙ain是靜態(tài)方法
(5)成員方法重名
方法重名大體也可以分兩種情況:
1、方法名相同返回值類型、參數(shù)列表卻不相同(優(yōu)先在子類查找,沒找到就去父類)
2、方法名、返回值類型、參數(shù)列表都相同,沒錯(cuò)這就是重寫(Override)
這里注意方法名相同不一定就是重寫
重寫的意義:
1、方法重寫時(shí), 方法名與形參列表必須一致。
2、子類方法覆蓋父類方法時(shí),必須要保證子類權(quán)限 >= 父類權(quán)限。
3、方法重寫時(shí),子類的返回值類型必須要 <= 父類的返回值類型。
4、方法重寫時(shí),子類拋出的異常類型要 <= 父類拋出的異常類型。
(6)繼承之后的構(gòu)造函數(shù)
構(gòu)造方法的名字是與類名一致的,所以子類是無法繼承父類構(gòu)造方法的。
構(gòu)造方法的作用是初始化成員變量的。所以子類的初始化過程中,必須先執(zhí)行父類的初始化動(dòng)作。子類的構(gòu)造方法中默認(rèn)會(huì)在第一句代碼中添加super(),表示調(diào)用父類的構(gòu)造方法,父類成員變量初始化后,才可以給子類使用。
當(dāng)然我已經(jīng)強(qiáng)調(diào)很多遍了 super() 不寫也默認(rèn)存在,而且只能是在第一句代碼中,不在第一句代碼中行不行,答案是當(dāng)然不行
(7)繼承后關(guān)于super和this
了解他們的用法之前必須明確一點(diǎn)的是父類空間優(yōu)先于子類對(duì)象產(chǎn)在每次創(chuàng)建子類對(duì)象時(shí),先初始化父類空間,再創(chuàng)建其子類對(duì)象本身。目的在于子類對(duì)象中包含了其對(duì)應(yīng)的父類空間,便可以包含其父類的成員,如果父類成員非private修飾,則子類可以隨意使用父類成員。代碼體現(xiàn)在子類的構(gòu) 造方法調(diào)用時(shí),一定先調(diào)用父類的構(gòu)造方法。
(7)類的每個(gè)構(gòu)造方法中均有 默認(rèn)的super(),調(diào)用父類的空參構(gòu)造。手動(dòng)調(diào)用父類構(gòu)造會(huì)覆蓋默認(rèn)的super()。
super() 和 this() 都必須是在構(gòu)造方法的第一行,所以不能同時(shí)出現(xiàn)。
3.多態(tài)
(1)多態(tài)定義:
高級(jí)定義:
程序中定義的引用變量所指向具體的類型和通過該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定,就叫多態(tài)
簡單定義:
多態(tài)指同一行為具有多種不同的表現(xiàn)形式
(2)多態(tài)三個(gè)前提:
繼承或者實(shí)現(xiàn)【二選一】
1.方法的重寫【意義體現(xiàn):不重寫,無意義】,子類對(duì)父類中某些方法進(jìn)行重新定義,在調(diào)用這些方法時(shí)就會(huì)調(diào)用子類的方法。
2.父類引用指向子類對(duì)象(也可以說向上轉(zhuǎn)型)【體現(xiàn)在格式上】
(3)多態(tài)的體現(xiàn):
多態(tài)體現(xiàn)的格式:
父類/父接口類型 變量名 = new 子類對(duì)象; 變量名.方法名()
當(dāng)使用多態(tài)調(diào)用方法的時(shí)候首先檢查父類中是否有該方法,如果沒有則編譯錯(cuò)誤,如果有執(zhí)行的是子類重寫后的方法(重中之重)
子類單獨(dú)定義方法丟失問題:
再來細(xì)品這一句話:
當(dāng)使用多態(tài)調(diào)用方法的時(shí)候首先檢查父類中是否有該方法,如果沒有則編譯錯(cuò)誤,如果有執(zhí)行的是子類重寫后的方法
來看一道題:
這應(yīng)該會(huì)打印什么:
有些聰明機(jī)智的童鞋已經(jīng)想到了,那些邊看博客邊走神的童鞋還在那想
一部分童鞋已經(jīng)饑渴難耐,迫不及待的回答這還不簡單肯定打印“我要走回學(xué)校”
博主此時(shí)亮出來答案:
此時(shí)很多童鞋想垃圾博主寫的什么垃圾結(jié)論還讓我們看兩遍
好了你們別嘀咕了且聽我慢慢扯來:
首先這是爺子輩的引用指向子類對(duì)象,當(dāng)爺子輩的引用調(diào)用方法的時(shí)候會(huì)先找自己的子類,其實(shí)子類B里邊沒有定義任何東西,所以那么這就是你們覺得是調(diào)用爺子輩f(xié)ly的原因了吧
but別忘了繼承啊,此時(shí)B里邊是有fly方法的,從你爺爺那繼承過來的,然后你爸爸還要找找自己的子類,發(fā)現(xiàn)你是它失散多年的兒子,它看看你有沒有fly你要是有的話就調(diào)用你的(由于你連女朋友都沒有所以你沒有后代),如果你沒有,你就繼承你爸爸的一份,然后再調(diào)用你的,懂了伐。。。。。
(4).靜態(tài)、動(dòng)態(tài)綁定本質(zhì)區(qū)別:
1、靜態(tài)綁定是發(fā)生在編譯階段;而動(dòng)態(tài)綁定是在運(yùn)行階段;
2、靜態(tài)綁定使用的是類信息,而動(dòng)態(tài)綁定使用的是對(duì)象信息
先看一個(gè)例子:
此時(shí)聰明的童鞋們都異口同聲地回答這不就是簡單多態(tài)嗎,肯定會(huì)輸出“我要飛回學(xué)校啊”
此時(shí)博主已經(jīng)急了,感覺打斷你們地思路悄悄地放出來答案
垃圾博主不看了,走走走兄弟們
哎哎哎再給我一次機(jī)會(huì)童鞋們
誒呀那么猴急干嘛,這不是給你們講靜態(tài)綁定呢嗎,細(xì)看代碼會(huì)發(fā)現(xiàn)父類和子類地方法中帶了static這就是所謂地靜態(tài)綁定,而以前不加地時(shí)候是動(dòng)態(tài)綁定,再細(xì)細(xì)品味兩者地區(qū)別,你就會(huì)發(fā)現(xiàn)其實(shí)靜態(tài)綁定就是一開始就已經(jīng)知道我要調(diào)用哪一個(gè),因?yàn)槌绦蜻€沒運(yùn)行,所以系統(tǒng)就默認(rèn)只要是父類地引用就調(diào)用父類的方法,但是動(dòng)態(tài)綁定就不一樣了,動(dòng)態(tài)綁定是在運(yùn)行階段綁定,運(yùn)行到父類引用調(diào)用方法時(shí)會(huì)動(dòng)態(tài)的去搜索子類有沒有重寫這個(gè)方法,然后決定執(zhí)行哪一個(gè)這就是多態(tài)
還有一個(gè)地方需要補(bǔ)充:
重載是靜態(tài)綁定,重寫是靜態(tài)綁定
(5)虛方法:
這垃圾博主有扯無大聊的(就是沒有用的)
不不不這與多態(tài)息息相關(guān)
可以把java中被重寫的方法稱為虛方法
(6)向上向下轉(zhuǎn)型(子類對(duì)象強(qiáng)制轉(zhuǎn)換成父類對(duì)象時(shí)并沒有丟失他原有的內(nèi)存空間只是暫時(shí)不可以訪問了所以可以再轉(zhuǎn)回成子對(duì)象)
向上轉(zhuǎn)型就是父類引用指向子類對(duì)象這個(gè)好理解
到這里,我們講解一下為什么要向下轉(zhuǎn)型,上面已經(jīng)講到過當(dāng)使用多態(tài)方式調(diào)用方法時(shí),首先檢查父類中是否有該方法,如果沒有,則編譯錯(cuò)誤。也就是說,不能調(diào)用子類擁有,而父類沒有的方法。編譯都錯(cuò)誤,更別說運(yùn)行了。這也是多態(tài)給我們帶來的麻煩。所以,想要調(diào)用子類特有的方法,必須做向下轉(zhuǎn)型。
這個(gè)時(shí)候我們的向下轉(zhuǎn)型就閃亮登場了
這樣func()就可以被調(diào)用了
注意只能存在繼承關(guān)系才能相互轉(zhuǎn)型,如果是不同的兩個(gè)類繼承了同一個(gè)類那么這兩個(gè)類是不能相互轉(zhuǎn)型的。還有一種向下轉(zhuǎn)型也不可取,就是一個(gè)父類的對(duì)象被強(qiáng)制轉(zhuǎn)換成一個(gè)子類的時(shí)候(當(dāng)然也轉(zhuǎn)不成功),子類的引用是不能指向這個(gè)對(duì)象的,即子類引用不能指向父類對(duì)象
(7)instanceof的使用:
instanceof 運(yùn)算符進(jìn)行判斷,左邊是對(duì)象右邊是類,當(dāng)對(duì)象是類或者子類創(chuàng)建的對(duì)象時(shí),返回true,否則返回false;
注意這里的的instanceof的格式,兩邊必須有繼承關(guān)系,這是格式問題,如果左邊的對(duì)象和右邊的類毛線關(guān)系都沒有那么編譯器就會(huì)報(bào)錯(cuò),也就是說只有左邊是父類的對(duì)象右邊是類的時(shí)候才會(huì)返回false
(8)多態(tài)與構(gòu)造器之間的妙用
看段代碼猜運(yùn)行結(jié)果(又來這招垃圾博主打死不猜了,反正也猜不對(duì))
好吧,博主就不賣關(guān)子了:
童鞋:就知道不按套路出牌,這垃圾博主
咳咳咳!!
好了別議論了
原因其實(shí)很簡單,因?yàn)樵趧?chuàng)建子類對(duì)象時(shí),會(huì)先去調(diào)用父類的構(gòu)造器,而父類構(gòu)造器中==又調(diào)用了被子類覆蓋的多態(tài)方法==,
由于父類并不清楚子類對(duì)象中的屬性值是什么(先初始化父類的時(shí)候還沒開始初始化子類),
于是把String類型的屬性暫時(shí)初始化為默認(rèn)值null,
然后再調(diào)用子類的構(gòu)造器(這個(gè)時(shí)子類構(gòu)造器已經(jīng)初始Weight屬性,所以子類構(gòu)造器知道熊孩子的體重Weight是250)。
好了我有點(diǎn)累了先休息一下
總結(jié)
以上是生活随笔為你收集整理的细品java封装继承多态的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小朋友你是否对java中的static满
- 下一篇: java的final也并不是那么高冷