詳細(xì)理解JAVA面向?qū)ο蟮姆庋b,繼承,多態(tài),抽象
創(chuàng)建類的對象 = 類的實例化 = 實例化類
類和對象的使用(面向?qū)ο笏枷肼涞氐膶崿F(xiàn)):
1.創(chuàng)建類,設(shè)計類的成員
2.創(chuàng)建類的對象
3.通過“對象.屬性”或“對象.方法”調(diào)用對象的結(jié)構(gòu)
如果創(chuàng)建了一個類的多個對象,則每個對象都獨立的擁有一套類的屬性。(非static的)
意味著,如果我們修改一個對象的屬性a,則不影響另外一個對象屬性a的值。
子類對象實例化的全過程
1.從結(jié)果上看:(繼承性)
- 子類繼承父類以后,就獲取了父類中聲明的屬性和方法。
- 創(chuàng)建子類的對象,在對空間中,就會加載所有父類中聲明的屬性。
2.從過程上來看:
當(dāng)我們通過子類的構(gòu)造器創(chuàng)建子類對象時,我們一定會直接或間接的調(diào)用其父類的構(gòu)造器,進(jìn)而調(diào)用父類的父類的構(gòu)造器。直到調(diào)用了java.lang.Object類中空參的構(gòu)造器為止。正因為加載過所有的父類的結(jié)構(gòu),所以才可以看到內(nèi)存中有父類的結(jié)構(gòu),子類對象才可以考慮進(jìn)行調(diào)用。
明確:雖然創(chuàng)建子類對象時,調(diào)用了父類的構(gòu)造器,但是自始至終就創(chuàng)建過一個對象,即為new的子類對象。
匿名對象
1. 理解:我們創(chuàng)建的對象,沒有顯式的賦給一個變量名,即為匿名對象
class Phone{ Phone p = new phone();//普通方式創(chuàng)建對象 p.sendEmail(); new Phone().sendEmail();//匿名對象只能直接調(diào)用方法 new Phone().price = 1999;//匿名對象調(diào)用屬性 }
2.特征:匿名對象只能使用一次
3.匿名對象在開發(fā)中的使用
class Phone{ public static void main(String[] args){ PhoneMall mall = new PhoneMall(); //匿名對象的使用 mall.show(new Phone()); } } class PhoneMall{ public void show(Phone phone){ phone.sendEmail(); } }
1.封裝性
封裝性的體現(xiàn):
我們將類的屬性xxx私有化(private),同時,提供公共的(public)方法來獲?。╣etXxx)和設(shè)置屬性
拓展:封裝性的體現(xiàn):A. 如上 B.不對外暴露的私有的方法 C.單例模式.....
封裝性的體現(xiàn),需要權(quán)限修飾符來配合。
1. Java規(guī)定的4中權(quán)限(從小到大排列):private、缺省、protected、public
2. 4種權(quán)限修飾符可以用來修飾類的內(nèi)部結(jié)構(gòu):屬性、方法、構(gòu)造器、內(nèi)部類
3. 修飾類的話,只能使用:缺省、public; public類可以在任意地方被訪問。
default類只可以被同一個包內(nèi)部的類訪問。
2.繼承性
繼承性的格式:class A extends B{}
A:子類、派生類、subclass
B:父類、超類、基類、superclass
體現(xiàn):一旦子類A繼承父類B以后,子類A中就獲取了父類B中聲明的所有的屬性和方法。
特別的,父類中聲明為private的屬性和方法,子類繼承父類以后,仍然認(rèn)為獲取了父類中私有的結(jié)構(gòu)。只是由于封裝性的影響,使得子類不能直接調(diào)用父類的結(jié)構(gòu)而已。
子類繼承父類以后,還可以聲明自己特有的屬性或方法,實現(xiàn)功能的擴展。子類和父類的關(guān)系,不同于子集和集合的關(guān)系。
Java中關(guān)于繼承性的規(guī)定:
1.一個類可以被多個子類繼承。
2.Java中類的單繼承性,一個類只能有一個父類
3.子父類是相對的概念。
4.之類直接繼承的父類,稱為:直接父類;間接繼承的父類稱為:間接父類
5.子類繼承父類以后,就獲取了直接父類以及所有間接父類中生命的屬性和方法
----------
1.如果我們沒有顯示的聲明一個列的父類的話,則此類繼承于java.lang.Object類
2.所有的java類(除java.lang.Object類之外)都直接或間接的繼承于java.lang.Object類
3.意味著,所有的java類具有java.lang.Object類聲明的功能。
繼承性的好處:
減少了代碼的冗余,提高了代碼的復(fù)用性便于功能的擴展;為之后多態(tài)性的使用,提供了前提。
在使用子類實例時,如果我們想要使用某些父類的屬性或方法,可以借助構(gòu)造器和封裝方法;如下:
public class Father{ //父類中的私有的屬性 private double ownMoney = 2000;//私房錢 //父類中的受保護的屬性 protected double money = 5000; //父類中的公開屬性 public String name = "老張"; }
public class Son extends Father{ //子類中的獨有屬性 ... //使用構(gòu)造器為屬性賦值 public Son(String name,double money){ super.name = name; super.money = money; } //使用封裝方法操作父類中的屬性 public void setMoney(double money){ super.money = money; } public double getMoney(){ return super.money; } }
public class Test{ public static void main(String[] args){ //在test包中的Test類中創(chuàng)建Son實例 Son son = new Son("小張",3000);//為父類繼承而來的屬性賦值 //以下代碼編譯通過 double money = son.getMoney(); System.out.println(money); son.setMoney(money - 500); } }
從以上的例子看到:測試類對于字符類來說是一個處在不同包中的完全無關(guān)的類,在調(diào)用時會被權(quán)限修飾符所限制,所以這里明確一下:權(quán)限修飾符是根據(jù)類的搜在路徑 與列之間的結(jié)構(gòu)關(guān)系驚醒限定的,不是說在任意一個地方使用子類實例都能調(diào)用出父類中的屬性和方法。
3.多態(tài)性
1.理解多態(tài)性:可以理解為一個事物的多種形態(tài)。
2.何為多態(tài)性:
- 對象的多態(tài)性:父類的引用指向子類的對象(或子類的對象賦給父類的引用)
3.多態(tài)的使用:虛擬方法調(diào)用
- 有了對象的多態(tài)性以后,我們在編譯期,只能調(diào)用父類中聲明的方法,但在運行期,我們實際執(zhí)行的是子類重寫父類的方法。
總結(jié):編譯,看左邊;運行,看右邊。
4.多態(tài)性的使用前提:A.存在子父類繼承關(guān)系 B.子類重寫父類的方法 C.父類引用指向子類對象
5.對象的多態(tài)性,只適用于方法,不適用于屬性(編譯和運行都看左邊)
5.1 若子類重寫了父類方法,就意味著子類里定義的方法徹底覆蓋了父類里的同名方法,系統(tǒng)將不可能把父類里的方法轉(zhuǎn)移到子類中,編譯看左邊,運行看右邊。
5.2 對于實例變量則不存在這樣的現(xiàn)象,即使子類里定義了與父類完全相同的實例變量,這個實例變量依然不可能覆蓋父類中定義的實例變量,編譯運行都看左邊。
6.多態(tài)的使用:當(dāng)調(diào)用子父類同名同參數(shù)的方法時,實際執(zhí)行的是子類重寫父類的方法----->虛擬方法調(diào)用
虛擬方法調(diào)用
正常的方法調(diào)用:
Person e = new Person(); e.getInfo(); Student e = new Student(); e.getInfo();
虛擬方法調(diào)用(多態(tài)情況下)
子類中定義了與父類同名同參數(shù)的方法,在多態(tài)情況下,將此時父類的方法稱為虛擬方法,父類根據(jù)賦給它的不同子類對象,動態(tài)調(diào)用屬于子類的該方法,這樣的方法調(diào)用在編譯期是無法確定的。
Person e = new Student(); e.getInfo();//調(diào)用Student類的getInfo()方法
編譯時類型和運行時類型
編譯時e為Person類型,而方法的調(diào)用時在運行時確定的,所以調(diào)用的是Student類的getInfo()方法。------動態(tài)綁定
public class PersonTest{ public static void main(String[] args){ Person p2 = new Man(); Person p3 = new Woman(); p2.name = "Tom"; //不能調(diào)用子類所特有的方法、屬性;編譯時,p2是Person類型。 // p2.earnMoney();//earnMoney()是子類Man()的方法 } }
有了對象的多態(tài)性以后,內(nèi)存中實際上是加載了子類特有的屬性和方法的,但是由于變量聲明為父類類型,導(dǎo)致編譯時,只能調(diào)用父類中聲明的屬性和方法,子類特有的屬性和方法不能調(diào)用。
如何才能調(diào)用子類特有的屬性和方法?
答:向下轉(zhuǎn)型,使用強制類型轉(zhuǎn)換符。
Man m1 = (Man)p2; m1.earnMoney(); //使用強轉(zhuǎn)時,可能出現(xiàn)ClassCastException的異常 Woman w1 = (Woman)p2;//p2是Man;兩者并列關(guān)系 w1.goShopping();
解決這個問題的辦法是先使用關(guān)鍵字(instanceof)判斷一下?。。。?! (會在下一篇博客關(guān)鍵字中介紹)
4.抽象性
背景:有兩個在邏輯上看似相關(guān)的類,我們想要把他們聯(lián)系起來,因為這樣做可以提高效率,例如:矩形、圓形,都可以具有周長和面積兩個方法,但是計算的方式完全不同,矩形和圓形之間肯定不能構(gòu)成子父類的關(guān)系,那么只能是同時去繼承一個父類。這時,就引出了抽象的概念。
1.抽象類的特點:
抽象類的本質(zhì)依然是一個類,所以具備著一個普通類的所有功能,包括構(gòu)造方法等的定義,總結(jié)一下,抽象類具有以下的幾個特點:
- A. 抽象類由abstract修飾
- B. 抽象類中允許出現(xiàn)抽象方法
- C.抽象了不能通過構(gòu)造器直接實例化
- D.可以在抽象類中定義普通方法供子類繼承。
public abstract class Figure{ //定義計算周長的抽象方法:getC() //抽象方法,不能有方法主體 public abstract double getC(); }
2.天生的父類:抽象類
2.1 抽象類不能直接實例化(編譯無法通過),是天生的父類
2.2 如果一個類繼承了抽象類,那么必須重寫父類中的抽象方法
2.3 如果抽象類中定義了構(gòu)造方法,可以被子類調(diào)用或在實例化子類對象時執(zhí)行
2.4 如果抽象類的子類依然是抽象類(需要用abstract聲明),可以不重寫抽象方法,將重寫操作留給下一級子類
2.5 抽象類不能使用final關(guān)鍵字修飾,因為final 修飾的類是無法被繼承
2.6 抽象類的匿名子類
public class PersonTest{ public static void main(String[] args){ method(new Student());//匿名對象 Worker worker = new Worker(); method1(worker);//非匿名的類非匿名的對象 method1(new Worker());//非匿名的類匿名的對象 //創(chuàng)建了一匿名子類的對象:p Person p = new Person(){ @Override public void eat(){ } } //創(chuàng)建匿名子類的匿名對象 method1(new Person()){ @Override public void eat(){ } } } } class Worker extends Person{ }
3.抽象方法
3.1 抽象類中的抽象方法只是聲明,不包含方法體
3.2 抽象方法不能用private修飾,因為抽象方法必須被子類實現(xiàn)(重寫),而private 權(quán)限對于子類來說是不能訪問的
3.3 一個類繼承了一個抽象類,那么它必須全部重寫抽象類中的抽象方法,當(dāng)然也可以不全部重寫,如果不重寫全部抽 象方法則這個子類也必須是抽象類
3.4 構(gòu)造方法,類方法(static修飾的方法)不能聲明為抽象方法
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
詳談HashMap和ConcurrentHashMap的區(qū)別(HashMap的底層源碼)
下面小編就為大家?guī)硪黄斦凥ashMap和ConcurrentHashMap的區(qū)別(HashMap的底層源碼)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08Java統(tǒng)計字符串中字符出現(xiàn)次數(shù)的方法示例
這篇文章主要介紹了Java統(tǒng)計字符串中字符出現(xiàn)次數(shù)的方法,涉及Java針對字符串的遍歷、查找、計算等相關(guān)操作技巧,需要的朋友可以參考下2017-12-12Java?Stream函數(shù)式編程管道流結(jié)果處理
這篇文章主要為大家介紹了Java?Stream函數(shù)式編程管道流結(jié)果處理的示例過程解析需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03SpringBoot整合Netty實現(xiàn)WebSocket的示例代碼
本文主要介紹了SpringBoot整合Netty實現(xiàn)WebSocket的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05利用Postman和Chrome的開發(fā)者功能探究項目(畢業(yè)設(shè)計項目)
這篇文章主要介紹了利用Postman和Chrome的開發(fā)者功能探究項目(畢業(yè)設(shè)計項目),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12