詳細(xì)理解JAVA面向?qū)ο蟮姆庋b,繼承,多態(tài),抽象
創(chuàng)建類的對(duì)象 = 類的實(shí)例化 = 實(shí)例化類
類和對(duì)象的使用(面向?qū)ο笏枷肼涞氐膶?shí)現(xiàn)):
1.創(chuàng)建類,設(shè)計(jì)類的成員
2.創(chuàng)建類的對(duì)象
3.通過(guò)“對(duì)象.屬性”或“對(duì)象.方法”調(diào)用對(duì)象的結(jié)構(gòu)
如果創(chuàng)建了一個(gè)類的多個(gè)對(duì)象,則每個(gè)對(duì)象都獨(dú)立的擁有一套類的屬性。(非static的)
意味著,如果我們修改一個(gè)對(duì)象的屬性a,則不影響另外一個(gè)對(duì)象屬性a的值。
子類對(duì)象實(shí)例化的全過(guò)程
1.從結(jié)果上看:(繼承性)
- 子類繼承父類以后,就獲取了父類中聲明的屬性和方法。
- 創(chuàng)建子類的對(duì)象,在對(duì)空間中,就會(huì)加載所有父類中聲明的屬性。
2.從過(guò)程上來(lái)看:
當(dāng)我們通過(guò)子類的構(gòu)造器創(chuàng)建子類對(duì)象時(shí),我們一定會(huì)直接或間接的調(diào)用其父類的構(gòu)造器,進(jìn)而調(diào)用父類的父類的構(gòu)造器。直到調(diào)用了java.lang.Object類中空參的構(gòu)造器為止。正因?yàn)榧虞d過(guò)所有的父類的結(jié)構(gòu),所以才可以看到內(nèi)存中有父類的結(jié)構(gòu),子類對(duì)象才可以考慮進(jìn)行調(diào)用。
明確:雖然創(chuàng)建子類對(duì)象時(shí),調(diào)用了父類的構(gòu)造器,但是自始至終就創(chuàng)建過(guò)一個(gè)對(duì)象,即為new的子類對(duì)象。
匿名對(duì)象
1. 理解:我們創(chuàng)建的對(duì)象,沒(méi)有顯式的賦給一個(gè)變量名,即為匿名對(duì)象
class Phone{
Phone p = new phone();//普通方式創(chuàng)建對(duì)象
p.sendEmail();
new Phone().sendEmail();//匿名對(duì)象只能直接調(diào)用方法
new Phone().price = 1999;//匿名對(duì)象調(diào)用屬性
}
2.特征:匿名對(duì)象只能使用一次
3.匿名對(duì)象在開(kāi)發(fā)中的使用
class Phone{
public static void main(String[] args){
PhoneMall mall = new PhoneMall();
//匿名對(duì)象的使用
mall.show(new Phone());
}
}
class PhoneMall{
public void show(Phone phone){
phone.sendEmail();
}
}
1.封裝性
封裝性的體現(xiàn):
我們將類的屬性xxx私有化(private),同時(shí),提供公共的(public)方法來(lái)獲?。╣etXxx)和設(shè)置屬性
拓展:封裝性的體現(xiàn):A. 如上 B.不對(duì)外暴露的私有的方法 C.單例模式.....
封裝性的體現(xiàn),需要權(quán)限修飾符來(lái)配合。
1. Java規(guī)定的4中權(quán)限(從小到大排列):private、缺省、protected、public
2. 4種權(quán)限修飾符可以用來(lái)修飾類的內(nèi)部結(jié)構(gòu):屬性、方法、構(gòu)造器、內(nèi)部類
3. 修飾類的話,只能使用:缺省、public; public類可以在任意地方被訪問(wèn)。
default類只可以被同一個(gè)包內(nèi)部的類訪問(wèn)。
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)而已。
子類繼承父類以后,還可以聲明自己特有的屬性或方法,實(shí)現(xiàn)功能的擴(kuò)展。子類和父類的關(guān)系,不同于子集和集合的關(guān)系。
Java中關(guān)于繼承性的規(guī)定:
1.一個(gè)類可以被多個(gè)子類繼承。
2.Java中類的單繼承性,一個(gè)類只能有一個(gè)父類
3.子父類是相對(duì)的概念。
4.之類直接繼承的父類,稱為:直接父類;間接繼承的父類稱為:間接父類
5.子類繼承父類以后,就獲取了直接父類以及所有間接父類中生命的屬性和方法
----------
1.如果我們沒(méi)有顯示的聲明一個(gè)列的父類的話,則此類繼承于java.lang.Object類
2.所有的java類(除java.lang.Object類之外)都直接或間接的繼承于java.lang.Object類
3.意味著,所有的java類具有java.lang.Object類聲明的功能。
繼承性的好處:
減少了代碼的冗余,提高了代碼的復(fù)用性便于功能的擴(kuò)展;為之后多態(tài)性的使用,提供了前提。
在使用子類實(shí)例時(shí),如果我們想要使用某些父類的屬性或方法,可以借助構(gòu)造器和封裝方法;如下:
public class Father{
//父類中的私有的屬性
private double ownMoney = 2000;//私房錢(qián)
//父類中的受保護(hù)的屬性
protected double money = 5000;
//父類中的公開(kāi)屬性
public String name = "老張";
}
public class Son extends Father{
//子類中的獨(dú)有屬性
...
//使用構(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實(shí)例
Son son = new Son("小張",3000);//為父類繼承而來(lái)的屬性賦值
//以下代碼編譯通過(guò)
double money = son.getMoney();
System.out.println(money);
son.setMoney(money - 500);
}
}
從以上的例子看到:測(cè)試類對(duì)于字符類來(lái)說(shuō)是一個(gè)處在不同包中的完全無(wú)關(guān)的類,在調(diào)用時(shí)會(huì)被權(quán)限修飾符所限制,所以這里明確一下:權(quán)限修飾符是根據(jù)類的搜在路徑 與列之間的結(jié)構(gòu)關(guān)系驚醒限定的,不是說(shuō)在任意一個(gè)地方使用子類實(shí)例都能調(diào)用出父類中的屬性和方法。
3.多態(tài)性
1.理解多態(tài)性:可以理解為一個(gè)事物的多種形態(tài)。
2.何為多態(tài)性:
- 對(duì)象的多態(tài)性:父類的引用指向子類的對(duì)象(或子類的對(duì)象賦給父類的引用)
3.多態(tài)的使用:虛擬方法調(diào)用
- 有了對(duì)象的多態(tài)性以后,我們?cè)诰幾g期,只能調(diào)用父類中聲明的方法,但在運(yùn)行期,我們實(shí)際執(zhí)行的是子類重寫(xiě)父類的方法。
總結(jié):編譯,看左邊;運(yùn)行,看右邊。
4.多態(tài)性的使用前提:A.存在子父類繼承關(guān)系 B.子類重寫(xiě)父類的方法 C.父類引用指向子類對(duì)象
5.對(duì)象的多態(tài)性,只適用于方法,不適用于屬性(編譯和運(yùn)行都看左邊)
5.1 若子類重寫(xiě)了父類方法,就意味著子類里定義的方法徹底覆蓋了父類里的同名方法,系統(tǒng)將不可能把父類里的方法轉(zhuǎn)移到子類中,編譯看左邊,運(yùn)行看右邊。
5.2 對(duì)于實(shí)例變量則不存在這樣的現(xiàn)象,即使子類里定義了與父類完全相同的實(shí)例變量,這個(gè)實(shí)例變量依然不可能覆蓋父類中定義的實(shí)例變量,編譯運(yùn)行都看左邊。
6.多態(tài)的使用:當(dāng)調(diào)用子父類同名同參數(shù)的方法時(shí),實(shí)際執(zhí)行的是子類重寫(xiě)父類的方法----->虛擬方法調(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)情況下,將此時(shí)父類的方法稱為虛擬方法,父類根據(jù)賦給它的不同子類對(duì)象,動(dòng)態(tài)調(diào)用屬于子類的該方法,這樣的方法調(diào)用在編譯期是無(wú)法確定的。
Person e = new Student(); e.getInfo();//調(diào)用Student類的getInfo()方法
編譯時(shí)類型和運(yùn)行時(shí)類型
編譯時(shí)e為Person類型,而方法的調(diào)用時(shí)在運(yùn)行時(shí)確定的,所以調(diào)用的是Student類的getInfo()方法。------動(dòng)態(tài)綁定
public class PersonTest{
public static void main(String[] args){
Person p2 = new Man();
Person p3 = new Woman();
p2.name = "Tom";
//不能調(diào)用子類所特有的方法、屬性;編譯時(shí),p2是Person類型。
// p2.earnMoney();//earnMoney()是子類Man()的方法
}
}
有了對(duì)象的多態(tài)性以后,內(nèi)存中實(shí)際上是加載了子類特有的屬性和方法的,但是由于變量聲明為父類類型,導(dǎo)致編譯時(shí),只能調(diào)用父類中聲明的屬性和方法,子類特有的屬性和方法不能調(diào)用。
如何才能調(diào)用子類特有的屬性和方法?
答:向下轉(zhuǎn)型,使用強(qiáng)制類型轉(zhuǎn)換符。
Man m1 = (Man)p2; m1.earnMoney(); //使用強(qiáng)轉(zhuǎn)時(shí),可能出現(xiàn)ClassCastException的異常 Woman w1 = (Woman)p2;//p2是Man;兩者并列關(guān)系 w1.goShopping();
解決這個(gè)問(wèn)題的辦法是先使用關(guān)鍵字(instanceof)判斷一下?。。。?! (會(huì)在下一篇博客關(guān)鍵字中介紹)
4.抽象性
背景:有兩個(gè)在邏輯上看似相關(guān)的類,我們想要把他們聯(lián)系起來(lái),因?yàn)檫@樣做可以提高效率,例如:矩形、圓形,都可以具有周長(zhǎng)和面積兩個(gè)方法,但是計(jì)算的方式完全不同,矩形和圓形之間肯定不能構(gòu)成子父類的關(guān)系,那么只能是同時(shí)去繼承一個(gè)父類。這時(shí),就引出了抽象的概念。
1.抽象類的特點(diǎn):
抽象類的本質(zhì)依然是一個(gè)類,所以具備著一個(gè)普通類的所有功能,包括構(gòu)造方法等的定義,總結(jié)一下,抽象類具有以下的幾個(gè)特點(diǎn):
- A. 抽象類由abstract修飾
- B. 抽象類中允許出現(xiàn)抽象方法
- C.抽象了不能通過(guò)構(gòu)造器直接實(shí)例化
- D.可以在抽象類中定義普通方法供子類繼承。
public abstract class Figure{
//定義計(jì)算周長(zhǎng)的抽象方法:getC()
//抽象方法,不能有方法主體
public abstract double getC();
}
2.天生的父類:抽象類
2.1 抽象類不能直接實(shí)例化(編譯無(wú)法通過(guò)),是天生的父類
2.2 如果一個(gè)類繼承了抽象類,那么必須重寫(xiě)父類中的抽象方法
2.3 如果抽象類中定義了構(gòu)造方法,可以被子類調(diào)用或在實(shí)例化子類對(duì)象時(shí)執(zhí)行
2.4 如果抽象類的子類依然是抽象類(需要用abstract聲明),可以不重寫(xiě)抽象方法,將重寫(xiě)操作留給下一級(jí)子類
2.5 抽象類不能使用final關(guān)鍵字修飾,因?yàn)閒inal 修飾的類是無(wú)法被繼承
2.6 抽象類的匿名子類
public class PersonTest{
public static void main(String[] args){
method(new Student());//匿名對(duì)象
Worker worker = new Worker();
method1(worker);//非匿名的類非匿名的對(duì)象
method1(new Worker());//非匿名的類匿名的對(duì)象
//創(chuàng)建了一匿名子類的對(duì)象:p
Person p = new Person(){
@Override
public void eat(){
}
}
//創(chuàng)建匿名子類的匿名對(duì)象
method1(new Person()){
@Override
public void eat(){
}
}
}
}
class Worker extends Person{
}
3.抽象方法
3.1 抽象類中的抽象方法只是聲明,不包含方法體
3.2 抽象方法不能用private修飾,因?yàn)槌橄蠓椒ū仨毐蛔宇悓?shí)現(xiàn)(重寫(xiě)),而private 權(quán)限對(duì)于子類來(lái)說(shuō)是不能訪問(wèn)的
3.3 一個(gè)類繼承了一個(gè)抽象類,那么它必須全部重寫(xiě)抽象類中的抽象方法,當(dāng)然也可以不全部重寫(xiě),如果不重寫(xiě)全部抽 象方法則這個(gè)子類也必須是抽象類
3.4 構(gòu)造方法,類方法(static修飾的方法)不能聲明為抽象方法
總結(jié)
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Spring Data JPA開(kāi)啟批量更新時(shí)樂(lè)觀鎖失效問(wèn)題的解決方法
樂(lè)觀鎖的基本思想是,認(rèn)為在大多數(shù)情況下,數(shù)據(jù)訪問(wèn)不會(huì)導(dǎo)致沖突,因此,樂(lè)觀鎖允許多個(gè)事務(wù)同時(shí)讀取和修改相同的數(shù)據(jù),而不進(jìn)行顯式的鎖定,本文給大家介紹了Spring Data JPA開(kāi)啟批量更新時(shí)樂(lè)觀鎖失效問(wèn)題的解決方法,需要的朋友可以參考下2024-07-07
Spring?Cloud?Gateway?整合?knife4j?聚合接口文檔功能
這篇文章主要介紹了Spring?Cloud?Gateway?整合?knife4j?聚合接口文檔的相關(guān)知識(shí),我們可以基于?Spring?Cloud?Gateway?網(wǎng)關(guān)?+?nacos?+?knife4j?對(duì)所有微服務(wù)項(xiàng)目的接口文檔進(jìn)行聚合,從而實(shí)現(xiàn)我們想要的文檔管理功能,需要的朋友可以參考下2022-02-02
SpringBoot集成本地緩存性能之王Caffeine示例詳解
這篇文章主要為大家介紹了SpringBoot集成本地緩存性能之王Caffeine的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
SpringBoot學(xué)習(xí)篇之@Valid與@Validated的區(qū)別
@Valid是使用Hibernate?validation的時(shí)候使用,@Validated是只用Spring?Validator校驗(yàn)機(jī)制使用,下面這篇文章主要給大家介紹了關(guān)于SpringBoot學(xué)習(xí)篇之@Valid與@Validated區(qū)別的相關(guān)資料,需要的朋友可以參考下2022-11-11
深入理解SpringMVC中央調(diào)度器DispatcherServlet
這篇文章主要介紹了SpringMVC核心之中央調(diào)度器DispatcherServlet的相關(guān)知識(shí),包括SpringMVC請(qǐng)求處理過(guò)程及SrpingMVC容器和spring?IOC容器關(guān)系,需要的朋友可以參考下2022-05-05
Java連接Mysql數(shù)據(jù)庫(kù)詳細(xì)代碼實(shí)例
這篇文章主要介紹了Java連接Mysql數(shù)據(jù)庫(kù)詳細(xì)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
關(guān)于Java 中的 Lambda 表達(dá)式
這篇文章主要介紹了關(guān)于Java 中的 Lambda 表達(dá)式,Lambda 表達(dá)式是 Java 涉足函數(shù)式編程的過(guò)程。它接受參數(shù)并將其應(yīng)用于表達(dá)式或代碼塊,下面一起進(jìn)入文章查看詳細(xì)內(nèi)容2021-11-11

