Java輕松掌握面向?qū)ο蟮娜筇匦苑庋b與繼承和多態(tài)
1.封裝
1.介紹
封裝是指把抽象出的屬性和方法封裝在一起,數(shù)據(jù)被保護在內(nèi)部,程序的其他部分只能通過被授權(quán)的方法,才能對數(shù)據(jù)操作。
2.封裝的理解和好處
- 隱藏實現(xiàn)的細(xì)節(jié)
- 可以對數(shù)據(jù)驗證,保證安全合理
3.封裝的實現(xiàn)步驟
- 將屬性私有化(private)
- 提供一個公共的set方法,用于對屬性判斷并賦值
- 提供一個公共的get方法,用于獲取屬性的值
public class Student { private Double score; public void setScore(Double score) { //還可以在這里進行屬性的判斷 this.score = score; } public Double getScore() { return score; }
2.繼承
1.介紹
繼承可以解決代碼的復(fù)用,當(dāng)多個類具有相同的屬性和方法時,我們可以從中抽象出父類,然后再父類中定義這些相同的屬性和方法,這樣所有的子類就不需要再定義這些相同的屬性和方法,只需要使用extends關(guān)鍵字來繼承父類即可。
2.繼承的基本語法
public class Graduate extends Student{ }
- 子類會自動擁有父類定義的屬性和方法
- 父類又叫基類,超類
- 子類又稱派生類
3.繼承的使用細(xì)節(jié)
子類繼承了父類所有的屬性和方法,但是私有屬性和方法不能在子類直接訪問,要通過公共的方法去訪問。
package com.wang.extend; public class Student {//父類 public int age; public String name; private Double score; String hobby; public Double getScore() { return score; }
package com.wang.extend; public class Graduate extends Student {//子類 public void test() { //子類不能直接訪問private屬性,要調(diào)用公共方法得到 System.out.println("大學(xué)生" + name + age + hobby + getScore()); } }
子類必須調(diào)用父類構(gòu)造器,完成父類的初始化,當(dāng)創(chuàng)建子類對象時,不管使用子類的哪一個構(gòu)造器,默認(rèn)會先去調(diào)用父類的無參構(gòu)造器,若父類沒有無參構(gòu)造器,則必須在子類構(gòu)造器中使用super()指定使用父類的哪個構(gòu)造器完成父類初始化,否則編譯失敗。
package com.wang.extend; public class Student {//父類 public int age; public String name; //public Student() { //} public Student(int age, String name) { this.age = age; this.name = name; }
package com.wang.extend; public class Graduate extends Student { public Graduate() { // super();//默認(rèn)會有一個調(diào)用父類無參構(gòu)造的方法super() //若父類沒有無參構(gòu)造器,必須用super()指定使用哪個構(gòu)造器 super(20,"小明"); } }
super()在使用時,需要放在第一行。
super()和this()都只能放在構(gòu)造器第一行,因此這兩個方法不能同時存在于同一個構(gòu)造器。
Java所有的類都是Object的子類。查看類的層級Ctrl+H。
父類構(gòu)造器的調(diào)用不限于直接父類!將一直向上追溯到Object類(頂級父類)。
子類最多繼承一個父類,java的單繼承機制。
不能濫用繼承,子類和父類要符合包含關(guān)系。比如,大學(xué)生包含在學(xué)生當(dāng)中,這是學(xué)生就可以是父類,大學(xué)生為子類。
3.super關(guān)鍵字
1.基本介紹
super代表的是父類的引用,用于訪問父類的屬性,方法,構(gòu)造器
2.基本語法
1.訪問父類的屬性/方法,但不能訪問父類的private屬性/方法
super.屬性名; super.方法名(形參列表);
2.訪問父類的構(gòu)造器
super(形參列表);//只能放在構(gòu)造器的第一句
3.細(xì)節(jié)與好處
1.父類屬性由父類初始化,子類的屬性子類初始化,分工明確。
2.當(dāng)子類與父類的成員重名時,若要訪問父類的成員,必須通過super。
3.super的訪問不限于直接父類,當(dāng)多個基類都有同名的成員,使用super訪問時遵循就近原則。
4.super與this的比較
區(qū)別點 | this | super |
---|---|---|
訪問屬性 | 先訪問本類的屬性,若本類沒有再去父類 | 只訪問父類的屬性 |
調(diào)用方法 | 先訪問本類的方法,若本類沒有再去父類 | 直接訪問父類的方法 |
調(diào)用構(gòu)造器 | 調(diào)用本類的構(gòu)造器,必須放第一句 | 調(diào)用父類的構(gòu)造器,必須放第一句 |
特殊 | 表示當(dāng)前對象 | 表示子類訪問父類對象 |
4.方法重寫
1.基本介紹
子類的一個方法與父類的名稱,返回類型,形參列表都一樣,稱子類是父類方法的重寫。
2.注意事項與使用細(xì)節(jié)
1.子類方法的返回類型與父類方法的返回類型相同或者父類返回類型的子類。
//正確示例 public Object a() //父類返回類型為Object public String a() //子類返回類型為String或者Object //Object是String的父類
2.子類方法不能縮小父類方法的訪問權(quán)限。
//接下來是錯誤示例 void display() //這是子類 子類訪問權(quán)限為 默認(rèn)的 public void display() //這是父類 父類訪問權(quán)限為public //public->默認(rèn)的 訪問權(quán)限變小所以報錯
3.重載與重寫的比較
名稱 | 發(fā)生范圍 | 方法名 | 形參列表 | 返回類型 | 修飾符 |
---|---|---|---|---|---|
重載 | 本類 | 必須相同 | 參數(shù)類型,個數(shù)或者順序中至少有一個不同 | 無要求 | 無要求 |
重寫 | 父子類 | 必須相同 | 必須相同 | 子類的返回類型相同或者是父類的返回類型的子類 | 不能縮小父類的訪問范圍 |
3.多態(tài)
1.基本介紹
方法或?qū)ο缶哂卸喾N形態(tài)。是面向?qū)ο蟮牡谌筇卣?,多態(tài)是建立在封裝和繼承基礎(chǔ)之上的。
2.具體體現(xiàn)
1.方法的多態(tài)
重寫和重載體現(xiàn)多態(tài)。
//重載 public int sum(int a,int b); public int sum(int a,int b,int c); //重寫 class A{ public void say(){ System.out.printf("A是父類~");} } class B extends A{ public void say() { System.out.printf("B是子類~");} }
2.對象的多態(tài)(重點)
- 一個對象的編譯類型和運行類型可以不一致。
- 編譯類型在定義對象時,就確定了,不能改變,運行類型可以變化。
- 定義時 = 的左邊是編譯類型,右邊是運行類型。
Animal animal = new Dog();//Animal是編譯類型,Dog是運行類型 animal = new cat();//編譯類型不能改變,運行類型可變
3.多態(tài)注意事項和細(xì)節(jié)討論
1.多態(tài)的前提
兩個對象(類)存在繼承關(guān)系。
2.屬性
沒有重寫,屬性的值是看編譯類型。
public class Tes { public static void main(String[] args) { A a = new B(); System.out.println(a.n); //這里輸出的是10,因為屬性的值要看編譯類型,a的編譯類型為A,所以輸出的是A的屬性 } } class A { public int n = 10; } class B extends A { public int n = 20; }
3.instance of
比較操作符,是用來判斷對象的運行類型是否為某類型或者某類型的子類型。
4.多態(tài)的向上轉(zhuǎn)型
- 本質(zhì):父類的引用指向了子類的對象。
- 語法:父類類型 引用名 = new 子類類型();
- 特點:可以調(diào)用父類中的所有成員(遵守訪問權(quán)限),不能調(diào)用子類的特有成員,但最終的運行結(jié)果看運行類型的具體實現(xiàn),能調(diào)用那些成員看編譯類型,具體運行看運行類型。
5.多態(tài)的向下轉(zhuǎn)型
- 語法:子類類型 引用名 = (子類類型) 父類引用;
- 只能強轉(zhuǎn)父類的引用,不能強轉(zhuǎn)父類的對象。
- 要求父類的引用必須指向的是當(dāng)前目標(biāo)類型的對象。
- 可以調(diào)用子類類型中的所有成員。
public class Test { public static void main(String[] args) { //向上轉(zhuǎn)型 A a = new B(); a.say(); //a.abc(); 方法abc為運行類型B類特有的編譯類型A類不能調(diào)用 //調(diào)用那些成員看編譯類型,具體運行看運行類型 //向下轉(zhuǎn)型 B b = (B) a; //父類的引用必須指向的是當(dāng)前目標(biāo)類型的對象 b.abc(); } } class A { public void say (){ System.out.println("A類的say()被調(diào)用"); } } class B extends A { public void abc(){ System.out.println("B類的abc()被調(diào)用"); } public void say (){ System.out.println("B類的say()被調(diào)用"); } }
運行結(jié)果如下:
6.Java動態(tài)綁定機制
當(dāng)調(diào)用對象的方法時,該方法會與該對象的內(nèi)存地址/運行類型綁定。
當(dāng)調(diào)用對象的屬性時,不存在動態(tài)綁定機制。
public class Test { public static void main(String[] args) { A a = new B();//A為編譯類型,B為運行類型 System.out.println(a.sum()); //B類中sum()沒注釋前 結(jié)果為 40 注釋后結(jié)果為 30 //注釋后會調(diào)用A類的sum方法但因為動態(tài)綁定機制sum中的getI方法調(diào)用的是B中的 System.out.println(a.sum1()); //B類中sum()沒注釋前 結(jié)果為 30 注釋后結(jié)果為 20 //調(diào)用A類的sum1,i由于是調(diào)用對象的屬性,不存在動態(tài)綁定機制,哪里聲明就調(diào)用哪的i=10 } } public class A { public int i = 10; public int sum() { return getI() + 10; } public int sum1() { return i + 10; } public int getI() { return i; } } public class B extends A { public int i = 20; // public int sum() { // return i + 20; // } // public int sum1() { // return i + 10; // } public int getI() { return i; } }
7.多態(tài)數(shù)組多態(tài)參數(shù)
多態(tài)數(shù)組
數(shù)組的定義類型為父類類型,里面保存的實際元素類型為子類類型和父類類型。
多態(tài)參數(shù)
方法定義的形參類型為父類類型,實際類型允許為子類類型。
示例:父類為Employee,子類為Worker和Manage
public class Test { public static void main(String[] args) { Test test = new Test(); Employee employee = new Employee("Bob",3000); Employee[] employee1 = new Employee[5];//多態(tài)數(shù)組 父類定義 Worker worker = new Worker("Tom",5000); Worker worker1 = new Worker("Kit",6000); Manager manager = new Manager("Smith",12000,100000); Manager manager1 = new Manager("Sab",15000,110000); employee1[0]=worker;//可放子類 employee1[1]=worker1; employee1[2]=manager; employee1[3]=manager1; employee1[4]=employee;//也可放本類 test.showEmpAnnal(worker);//多態(tài)參數(shù) 實參可為子類 test.showEmpAnnal(manager); test.testwork(employee1); } public void showEmpAnnal(Employee e){//多態(tài)參數(shù) 形參為父類 System.out.println(e.getName()+" 的年薪為:"+e.getAnnual()); } public void testwork(Employee e[]){ for (int i = 0; i <5 ; i++) { if(e[i] instanceof Worker){ ((Worker) e[i]).work();//向下轉(zhuǎn)型 }else if(e[i] instanceof Manager){ ((Manager) e[i]).manage(); }else { System.out.println("員工 "+e[i].getName()+" 正在摸魚!"); } } } }
到此這篇關(guān)于Java輕松掌握面向?qū)ο蟮娜筇匦苑庋b與繼承和多態(tài)的文章就介紹到這了,更多相關(guān)Java封裝 繼承 多態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Elasticsearch5.4的常見問題總結(jié)
下面小編就為大家分享一篇基于Elasticsearch5.4的常見問題總結(jié),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01SpringBoot服務(wù)訪問路徑動態(tài)處理方式
這篇文章主要介紹了SpringBoot服務(wù)訪問路徑動態(tài)處理方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12