JAVA中方法的聲明及使用方式(繼承、多態(tài)、封裝)
一、寫在前面
今天就來總結(jié)一下JAVA中方法的聲明及使用,即繼承、多態(tài)、封裝。
其實(shí)關(guān)于三大特性對于學(xué)習(xí)JAVA的同學(xué)來說都是基本的了,畢竟只要接觸Java這些都是先要認(rèn)識的,接下來就系統(tǒng)總結(jié)一下。
二、繼承
先來說說繼承,所謂繼承本質(zhì)就是實(shí)現(xiàn)代碼的復(fù)用,防止重復(fù)的代碼多次書寫,當(dāng)一個(gè)類繼承一個(gè)類的時(shí)候,該類中就會(huì)擁有另外一個(gè)類中的所有代碼
2.1 繼承的注意事項(xiàng)
只支持單繼承,即一個(gè)子類只允許有一個(gè)父類,但是可以實(shí)現(xiàn)多級繼承,及子類擁有唯一的父類,而父類還可以再繼承。
子類可以擁有父類的屬性和方法。
子類可以擁有自己的屬性和方法。
子類可以重寫覆蓋父類的方法。
2.2 繼承的特點(diǎn)
- 提高代碼復(fù)用性。
- 父類的屬性方法可以用于子類。
- 可以輕松的定義子類。
- 使設(shè)計(jì)應(yīng)用程序變得簡單。
2.3 繼承的使用
1,在父子類關(guān)系繼承中,如果成員變量重名,則創(chuàng)建子類對象時(shí),訪問有兩種方式。
a:直接通過子類對象訪問成員變量
List item
等號左邊是誰,就優(yōu)先使用誰,如果沒有就向上找。
b:間接通過成員方法訪問成員變量
該方法屬于誰,誰就優(yōu)先使用,如果沒有就向上找。
public class FU { int numFU = 10; int num = 100; public void method(){ System.out.println("父類成員變量:"+numFU); } public void methodFU(){ System.out.println("父類成員方法!"); } } public class Zi extends FU{ int numZi = 20; int num = 200; public void method(){ System.out.println("子類成員變量:"+numFU); } public void methodZi(){ System.out.println("子類方法!"); } }
public class ExtendDemo { public static void main(String[] args) { FU fu = new FU(); // 父類的實(shí)體對象只能調(diào)用父類的成員變量 System.out.println("父類:" + fu.numFU); // 結(jié)果:10 Zi zi = new Zi(); System.out.println("調(diào)用父類:" + zi.numFU); // 結(jié)果:10 System.out.println("子類:" + zi.numZi); // 結(jié)果:20 /** 輸出結(jié)果為200,證明在重名情況下,如果子類中存在則優(yōu)先使用, * 如果不存在則去父類查找,但如果父類也沒有那么編譯期就會(huì)報(bào)錯(cuò)。 */ System.out.println(zi.num); // 結(jié)果:200 /** * 通過成員方法調(diào)用成員變量 */ zi.method(); // 結(jié)果:10 } }
2,同理:
? 成員方法也是一樣的,創(chuàng)建的對象是誰,就優(yōu)先使用誰,如果沒有則直接向上找。
? 注意事項(xiàng):
? 無論是成員變量還是成員方法,如果沒有都是向上父類中查找,絕對不會(huì)向下查找子類的。
3,在繼承關(guān)系中,關(guān)于成員變量的使用:
- 局部成員變量:直接使用
- 本類成員變量:this.成員變量
- 父類成員變量:super.父類成員變量
int numZi = 10; public void method() { int numMethod = 20; System.out.println(numMethod); // 訪問局部變量 System.out.println(this.numZi); // 訪問本類成員變量
2.4 重寫和重載
2.4.1 重寫(override)
重寫是子類對父類的允許訪問的方法的實(shí)現(xiàn)過程進(jìn)行重新編寫, 返回值和形參都不能改變。
即外殼不變,核心重寫!
class Animal{ public void move(){ System.out.println("動(dòng)物行走!"); } } class Dog extends Animal{ public void move(){ System.out.println("狗可以跑和走"); } } public class TestDog{ public static void main(String args[]){ Animal a = new Animal(); // Animal 對象 Animal b = new Dog(); // Dog 對象 a.move();// 執(zhí)行 Animal 類的方法 b.move();//執(zhí)行 Dog 類的方法 } }
重寫的規(guī)則:
1,參數(shù)列表必須與被重寫方法相同。
2,訪問權(quán)限不能比父類中被重寫的方法的訪問權(quán)限更低(public>protected>(default)>private)。
3,父類成員的方法只能被它的子類重寫。
4,被final修飾的方法不能被重寫。
5,構(gòu)造方法不能
2.4.2 重載(overload)
重載是在一個(gè)類里面,方法名字相同,而參數(shù)不同。返回類型可以相同也可以不同。每個(gè)重載的方法(或者構(gòu)造函數(shù))都必須有一個(gè)獨(dú)一無二的參數(shù)類型列表。
? 最常用的地方就是構(gòu)造器的重載。
public class Overloading { public int test(){ System.out.println("test1"); return 1; } public void test(int a){ System.out.println("test2"); } //以下兩個(gè)參數(shù)類型順序不同 public String test(int a,String s){ System.out.println("test3"); return "returntest3"; } public String test(String s,int a){ System.out.println("test4"); return "returntest4"; } public static void main(String[] args){ Overloading o = new Overloading(); System.out.println(o.test()); o.test(1); System.out.println(o.test(1,"test3")); System.out.println(o.test("test4",1)); } }
重載規(guī)則:
1,被重載的方法必須改變參數(shù)列表(參數(shù)個(gè)數(shù)或者類型不一樣)。
2,被重載的方法可以改變返回類型。
3,被重載的方法可以改變訪問修飾符。
2.4.3 this,super關(guān)鍵字
super()關(guān)鍵字的用法:
- 子類的成員方法中,訪問父類的成員變量。
- 子類的成員方法中,訪問父類的成員方法。
- 子類的構(gòu)造方法中,訪問父類的構(gòu)造方法。
this關(guān)鍵字用法:
- 本類成員方法中,訪問本類的成員變量。
- 本類成員方法中,訪問本類的另一個(gè)成員方法。
- 本類的構(gòu)造方法中,訪問本類的另一個(gè)構(gòu)造方法。
? 注意:
this關(guān)鍵字同super一樣,必須在構(gòu)造方法的第一個(gè)語句,且是唯一的。
this與super不能同時(shí)存在。
2.4.4 補(bǔ)充概念
隱藏
父類和子類擁有相同名字的屬性或者方法( 方法隱藏只有一種形式,就是父類和子類存在相同的靜態(tài)方法)時(shí),父類的同名的屬性或者方法形式上不見了,實(shí)際是還是存在的。
隱藏是對于靜態(tài)方法和成員變量(靜態(tài)變量和實(shí)例變量)而言的
public class Animal { String name; int age; int legs; public void eat(){ System.out.println("動(dòng)物要吃飯"); }; //類方法,靜態(tài)方法 //通過類就可以直接調(diào)用 public static void run(){ System.out.println("動(dòng)物在奔跑"); } } public class Cat extends Animal { //重寫父類方法 public void eat() { System.out.println("小貓吃魚"); } //隱藏父類的run方法 public static void run(){ System.out.println("小貓?jiān)诒寂?); } }
對象轉(zhuǎn)型
引用類型和對象類型不一致的情況下的轉(zhuǎn)換問題
子類轉(zhuǎn)父類(向上轉(zhuǎn)型)
Animal a = new Animal(); Cat c = new Cat(); a = c;
一個(gè)很簡單的判別辦法,把右邊的當(dāng)做左邊來用,看說得通不。右邊c引用所指向的對象的類型是 貓
左邊a引用的類型是 普通動(dòng)物,把貓 當(dāng)做 普通動(dòng)物,說不說得通? 說得通,就可以轉(zhuǎn)
父類轉(zhuǎn)子類(向下轉(zhuǎn)型)
父類轉(zhuǎn)子類,有的時(shí)候行,有的時(shí)候不行,所以必須進(jìn)行強(qiáng)制轉(zhuǎn)換。強(qiáng)制轉(zhuǎn)換的意思就是 轉(zhuǎn)換有風(fēng)險(xiǎn),風(fēng)險(xiǎn)自擔(dān)。
可以的情況
Animal a = new Animal(); Cat c = new Cat(); a = c; c = (Cat) a; 不可以的情況 Animal a = new Animal(); Cat c = new Cat(); Dog d = new Dog(); a = d; c = (Cat) a; 沒有繼承關(guān)系的兩個(gè)類,互相轉(zhuǎn)換
沒有繼承關(guān)系的兩個(gè)類,互相轉(zhuǎn)換,一定會(huì)失敗。
雖然Cat和Dog都繼承了Animal,但是彼此沒有互相繼承關(guān)系
- 實(shí)現(xiàn)類轉(zhuǎn)換成接口(向上轉(zhuǎn)型)
- 接口轉(zhuǎn)換成實(shí)現(xiàn)類(向下轉(zhuǎn)型)
構(gòu)造器
子類是不繼承父類的構(gòu)造器(構(gòu)造方法或者構(gòu)造函數(shù))的,它只是調(diào)用(隱式或顯式)。
如果父類的構(gòu)造器帶有參數(shù),則必須在子類的構(gòu)造器中顯式地通過 super 關(guān)鍵字調(diào)用父類的構(gòu)造器并配以適當(dāng)?shù)膮?shù)列表。
如果父類構(gòu)造器沒有參數(shù),則在子類的構(gòu)造器中不需要使用 super 關(guān)鍵字調(diào)用父類構(gòu)造器,系統(tǒng)會(huì)自動(dòng)調(diào)用父類的無參構(gòu)造器。
三、多態(tài)
3.1 定義和優(yōu)點(diǎn)
定義:
- 多態(tài)是同一個(gè)行為具有多個(gè)不同表現(xiàn)形式或形態(tài)的能力。
- 多態(tài)就是同一個(gè)接口,使用不同的實(shí)例而執(zhí)行不同操作。
優(yōu)點(diǎn):
- 1. 消除類型之間的耦合關(guān)系;
- 2. 可替換性;
- 3. 可擴(kuò)充性;
- 4. 接口性;
- 5. 靈活性;
- 6. 簡化性;
3.2 多態(tài)的體現(xiàn)形式
繼承父類引用指向子類重寫
注意:在多態(tài)中,編譯看左邊,運(yùn)行看右邊
public class MultiDemo { public static void main(String[] args) { // 多態(tài)的引用,就是向上轉(zhuǎn)型 Animals dog = new Dog(); dog.eat(); Animals cat = new Cat(); cat.eat(); // 如果要調(diào)用父類中沒有的方法,則要向下轉(zhuǎn)型 Dog dogDown = (Dog)dog; dogDown.watchDoor(); } } class Animals { public void eat(){ System.out.println("動(dòng)物吃飯!"); } } class Dog extends Animals{ public void eat(){ System.out.println("狗在吃骨頭!"); } public void watchDoor(){ System.out.println("狗看門!"); } } class Cat extends Animals{ public void eat(){ System.out.println("貓?jiān)诔贼~!"); } }
例如:
在設(shè)計(jì)房子時(shí),大門的設(shè)計(jì)應(yīng)該開進(jìn)不同型號車輛,如打開一扇門,可以開進(jìn)摩托車;打開兩扇門,可以開進(jìn)小汽車;如果需要,打開三扇門,允許開進(jìn)貨車等。
同樣是門,由于不同參數(shù),可以完成不同的功能,這個(gè)門具有多態(tài)性。
3.3 向上轉(zhuǎn)型
- 格式:父類名稱 對象名 = new 子類名稱();
- 含義:右側(cè)創(chuàng)建一個(gè)子類對象,把它當(dāng)作父類來使用。
- 注意:向上轉(zhuǎn)型一定是安全的。
- 缺點(diǎn):一旦向上轉(zhuǎn)型,子類中原本特有的方法就不能再被調(diào)用了。
四、封裝
4.1 封裝的特性
在面向?qū)ο蟪淌皆O(shè)計(jì)方法中,封裝(Encapsulation)是指一種將抽象性函式接口的實(shí)現(xiàn)細(xì)節(jié)部分包裝、隱藏起來的方法。
封裝可以被認(rèn)為是一個(gè)保護(hù)屏障,防止該類的代碼和數(shù)據(jù)被外部類定義的代碼隨機(jī)訪問;要訪問該類的代碼和數(shù)據(jù),必須通過嚴(yán)格的接口控制;封裝最主要的功能在于我們能修改自己的實(shí)現(xiàn)代碼,而不用修改那些調(diào)用我們代碼的程序片段;適當(dāng)?shù)姆庋b可以讓程式碼更容易理解與維護(hù),也加強(qiáng)了程式碼的安全性。
封裝的特點(diǎn)
- 對成員變量實(shí)行更準(zhǔn)確的控制。
- 封裝可以隱藏內(nèi)部程序?qū)崿F(xiàn)的細(xì)節(jié)。
- 良好的封裝能夠減少代碼之間的耦合度。
- 外部成員無法修改已封裝好的程序代碼。方便數(shù)據(jù)檢查,有利于保護(hù)對象信息的完整性,同時(shí)也提高程序的安全性。便于修改,體高代碼的可維護(hù)性。
4.2 封裝的實(shí)現(xiàn)
使用private修飾符,表示最小的訪問權(quán)限。
對成員變量的訪問,統(tǒng)一提供setXXX,getXXX方法。
下面請看一個(gè)Student實(shí)體對象類:
public class Student implements Serializable { private Long id; private String name; private Integer sex; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } }
分析:對于上面的一個(gè)實(shí)體對象,我想大家都已經(jīng)很熟悉了。將對象中的成員變量進(jìn)行私有化,外部程序是無法訪問的。但是我們對外提供了訪問的方式,就是set和get方法。
? 而對于這樣一個(gè)實(shí)體對象,外部程序只有賦值和獲取值的權(quán)限,是無法對內(nèi)部進(jìn)行修改,因此我們還可以在內(nèi)部進(jìn)行一些邏輯上的判斷等,來完成我們業(yè)務(wù)上的需要。
? 到這里應(yīng)該就明白封裝對于我們的程序是多么重要。下面再來說說繼承的那點(diǎn)事。
修改屬性的可見性來限制對屬性的訪問(一般限制為private),例如
```java public class People { //將 name 和 age 屬性設(shè)置為私有的,只能本類才能訪問,其他類都訪問不了,如此就對信息進(jìn)行了隱藏。 private String name; private int age; }
對每個(gè)值屬性提供對外的公共方法訪問,也就是創(chuàng)建一對賦取值方法,用于對私有屬性的訪問,例如:
public class People{ //采用 this 關(guān)鍵字是為了解決實(shí)例變量(private String name)和局部變量(setName(String name)中的name變量)之間發(fā)生的同名的沖突。 private String name; private int age; ? public String getName(){ return name; } ? public void setName(String name){ this.name = name; } }
4.3 成員的訪問權(quán)限
Java提供了三個(gè)訪問控制符:private、protected和public,分別代表三個(gè)訪問控制級別。
default訪問控制權(quán)限(包訪問權(quán)限)
如果類里的一個(gè)成員不使用任何訪問控制符修飾,則使用default默認(rèn)訪問控制,default訪問控制的成員可以被相同包下其他類訪問。
protected訪問控制權(quán)限(子類訪問權(quán)限)
如果一個(gè)成員使用protected訪問控制符修飾,那么這個(gè)成員即可以被同一包中其他類訪問,也可以被不同包中的子類訪問。
public訪問控制權(quán)限(公共訪問權(quán)限)
如果一個(gè)成員使用public訪問控制符修飾,則可以被所有類訪問。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring項(xiàng)目中使用Junit單元測試并配置數(shù)據(jù)源的操作
這篇文章主要介紹了Spring項(xiàng)目中使用Junit單元測試并配置數(shù)據(jù)源的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09SpringBoot2如何集成Elasticsearch6.x(TransportClient方式)
這篇文章主要介紹了SpringBoot2如何集成Elasticsearch6.x(TransportClient方式)問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05springboot整合quartz實(shí)現(xiàn)定時(shí)任務(wù)示例
spring支持多種定時(shí)任務(wù)的實(shí)現(xiàn)。我們來介紹下使用spring的定時(shí)器和使用quartz定時(shí)器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-04-04使用springboot單元測試對weblistener的加載測試
這篇文章主要介紹了使用springboot單元測試對weblistener的加載測試,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10Mybatisplus創(chuàng)建Spring?Boot工程打包錯(cuò)誤的解決方式
最近在實(shí)戰(zhàn)springboot遇到了一些坑,記錄一下,下面這篇文章主要給大家介紹了關(guān)于Mybatisplus創(chuàng)建Spring?Boot工程打包錯(cuò)誤的解決方式,文中通過圖文介紹的介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03解決BufferedReader.readLine()遇見的坑
這篇文章主要介紹了解決BufferedReader.readLine()遇見的坑,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12java多線程關(guān)鍵字final和static詳解
這篇文章主要介紹了java多線程關(guān)鍵字final和static詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01