Java 繼承與多態(tài)超詳細(xì)梳理
一、繼承
1、繼承的概念
繼承機(jī)制:是面向?qū)ο蟪绦蛟O(shè)計(jì)是代碼可以復(fù)用的最重要手段,允許程序員在保持原有類(lèi)特性的基礎(chǔ)上進(jìn)行擴(kuò)展,增加新的功能,產(chǎn)生的新類(lèi),成為派生類(lèi)/子類(lèi)。繼承主要解決的問(wèn)題是:共性的抽取,實(shí)現(xiàn)代碼的復(fù)用。

2、繼承的語(yǔ)法
表示類(lèi)與類(lèi)的繼承關(guān)系,需要借助關(guān)鍵字extends,語(yǔ)法如下:
修飾符 class 子類(lèi)/派生類(lèi) extends 父類(lèi)/基類(lèi)/超類(lèi){
//…………
}
- 子類(lèi)會(huì)將父類(lèi)的成員變量或者成員方法繼承到子類(lèi)中
- 子類(lèi)繼承父類(lèi)后,必須添加自己特有的成員,體現(xiàn)與基類(lèi)的不同
3、父類(lèi)成員訪問(wèn)
(1)子類(lèi)中訪問(wèn)父類(lèi)的成員變量
- 不存在同名成員變量時(shí),正常訪問(wèn)就行
- 存在同名成員變量,使用(super.變量名)實(shí)現(xiàn)父類(lèi)成員變量的訪問(wèn)
public class Base {
int a;
int b;
int c;
}
public class Derived extends Base{
int a; // 與父類(lèi)中成員a同名,且類(lèi)型相同
char b; // 與父類(lèi)中成員b同名,但類(lèi)型不同
public void method(){
a = 100; // 訪問(wèn)父類(lèi)繼承的a,還是子類(lèi)自己新增的a?
b = 101; // 訪問(wèn)父類(lèi)繼承的b,還是子類(lèi)自己新增的b?
c = 102; // 子類(lèi)沒(méi)有c,訪問(wèn)的肯定是從父類(lèi)繼承下來(lái)的c
}
}- 訪問(wèn)成員變量時(shí),優(yōu)先訪問(wèn)自己的成員變量。即同名成員變量訪問(wèn)時(shí),優(yōu)先訪問(wèn)子類(lèi)的。即:子類(lèi)將父類(lèi)的成員隱藏了
- 成員變量訪問(wèn)遵循就近原則,自己有優(yōu)先自己的,自己沒(méi)有則向父類(lèi)中查找。
(2)子類(lèi)中訪問(wèn)父類(lèi)的成員方法
- 成員方法名字不同,正常訪問(wèn)即可
- 成員方法名字相同,可以通過(guò) 【super.方法名】訪問(wèn)同名父類(lèi)方法
如果父類(lèi)和子類(lèi)同名方法的參數(shù)列表不同(重載),根據(jù)調(diào)用方法時(shí)傳遞的參數(shù)選擇合適的方法訪問(wèn)。
如果父類(lèi)和子類(lèi)的同名方法原型一致,則訪問(wèn)子類(lèi)的
4、super關(guān)鍵字
super關(guān)鍵字的主要作用是:在子類(lèi)方法中訪問(wèn)父類(lèi)的同名成員。(只能在非靜態(tài)方法中使用)
public class Base {
int a;
int b;
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
public class Derived extends Base{
int a;
char b;
// 與父類(lèi)中methodA()構(gòu)成重載
public void methodA(int a) {
System.out.println("Derived中的method()方法");
}
// 與父類(lèi)中methodB()構(gòu)成重寫(xiě)
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
a = 100; // 等價(jià)于: this.a = 100;
b = 101; // 等價(jià)于: this.b = 101;
// 訪問(wèn)父類(lèi)的成員變量時(shí),需要借助super關(guān)鍵字
// super是獲取到子類(lèi)對(duì)象中從基類(lèi)繼承下來(lái)的部分
super.a = 200;
super.b = 201;
methodA(); // 沒(méi)有傳參,訪問(wèn)父類(lèi)中的methodA()
methodA(20); // 傳遞int參數(shù),訪問(wèn)子類(lèi)中的methodA(int)
methodB(); // 直接訪問(wèn),則永遠(yuǎn)訪問(wèn)到的都是子類(lèi)中的methodA(),基類(lèi)的無(wú)法訪問(wèn)到
super.methodB(); // 訪問(wèn)基類(lèi)的methodB()
}
}5、子類(lèi)構(gòu)造方法
子類(lèi)對(duì)象構(gòu)造時(shí),需要先調(diào)用父類(lèi)的構(gòu)造方法,然后執(zhí)行子類(lèi)的構(gòu)造方法。
public class Base {
public Base(){
System.out.println("Base()");
}
}
public class Derived extends Base{
public Derived(){
// super(); // 注意子類(lèi)構(gòu)造方法中默認(rèn)會(huì)調(diào)用基類(lèi)的無(wú)參構(gòu)造方法:super(),
// 用戶(hù)沒(méi)有寫(xiě)時(shí),編譯器會(huì)自動(dòng)添加,而且super()必須是子類(lèi)構(gòu)造方法中第一條語(yǔ)句,
// 并且只能出現(xiàn)一次
System.out.println("Derived()");
}
}- 若父類(lèi)顯示定義無(wú)參或者默認(rèn)的構(gòu)造函數(shù),在子類(lèi)的構(gòu)造方法第一行默認(rèn)有隱含的super()調(diào)用。
- 父類(lèi)定義帶參數(shù)的構(gòu)造方法時(shí),編譯器不會(huì)再給子類(lèi)生成默認(rèn)的構(gòu)造方法,需要子類(lèi)顯式定義,并在子類(lèi)構(gòu)造方法中調(diào)用合適的父類(lèi)構(gòu)造方法
- 子類(lèi)構(gòu)造方法中,super(……)調(diào)用父類(lèi)構(gòu)造方法,必須是子類(lèi)構(gòu)造方法的第一條語(yǔ)句
- super(……)只能在子類(lèi)構(gòu)造方法中出現(xiàn)一次,并且不能和this同時(shí)出現(xiàn)
6、super和this
super和this都可以在成員方法中用來(lái)訪問(wèn)成員變量和調(diào)用其他的成員函數(shù),都可以作為構(gòu)造方法的第一條語(yǔ)句,那么它們之間的區(qū)別是什么?
(1)相同點(diǎn)
- 都是java的關(guān)鍵字
- 只能在類(lèi)的非靜態(tài)方法中使用,用來(lái)訪問(wèn)非靜態(tài)成員方法和屬性
- 必須作為構(gòu)造方法中的第一條語(yǔ)句,并且不能同時(shí)存在
(2)不同點(diǎn)
- this是當(dāng)前對(duì)象的引用,super是子類(lèi)對(duì)象中從父類(lèi)繼承的成員的引用
- this是非靜態(tài)成員方法的一個(gè)隱藏參數(shù),super不是隱藏參數(shù)
- 在構(gòu)造方法中:this()用于調(diào)用本類(lèi)的構(gòu)造方法,super()用來(lái)調(diào)用父類(lèi)構(gòu)造方法,兩種調(diào)用不能同時(shí)出現(xiàn)在構(gòu)造方法中
- 子類(lèi)的構(gòu)造方法中一定會(huì)存在super()的調(diào)用,但是this()用戶(hù)不寫(xiě)就沒(méi)有
7、代碼塊執(zhí)行順序
【普通類(lèi)】
- 靜態(tài)代碼塊先執(zhí)行,并且只執(zhí)行一次,在類(lèi)加載階段執(zhí)行
- 當(dāng)有對(duì)象創(chuàng)建時(shí),才會(huì)執(zhí)行實(shí)例代碼塊,最后執(zhí)行構(gòu)造方法
【繼承關(guān)系上的執(zhí)行順序】
- 父類(lèi)靜態(tài)代碼塊優(yōu)先于子類(lèi)靜態(tài)代碼塊執(zhí)行,最早執(zhí)行
- 父類(lèi)實(shí)例代碼塊和父類(lèi)構(gòu)造方法緊接著執(zhí)行
- 子類(lèi)的實(shí)例代碼塊和構(gòu)造方法最后執(zhí)行
- 第二次實(shí)例化子類(lèi)對(duì)象時(shí),父類(lèi)和子類(lèi)的靜態(tài)代碼塊不會(huì)再執(zhí)行
8、繼承方式
【注】Java中不支持多繼承

- super只能指代直接父類(lèi)
- 繼承關(guān)系一般不超過(guò)三層
9、final關(guān)鍵字
- 修飾變量時(shí),表示常量(不能修改)
- 修飾類(lèi):此類(lèi)不能被繼承
- 修飾方法:表示方法不能被重寫(xiě)
10、繼承和組合
組合和繼承都能實(shí)現(xiàn)代碼的復(fù)用。組合沒(méi)有涉及到特殊的語(yǔ)法(如extend關(guān)鍵字),僅僅是將一個(gè)類(lèi)的實(shí)例作為另一個(gè)類(lèi)的屬性。
- 繼承表示對(duì)象與對(duì)象之間是is-a的關(guān)系
- 組合表示對(duì)象與對(duì)象之間是has-a的關(guān)系
一般建議:能用組合盡量用組合
二、多態(tài)
1、向上轉(zhuǎn)型
通過(guò)父類(lèi)類(lèi)型的引用調(diào)用子類(lèi)對(duì)象,向上轉(zhuǎn)型是安全的
【發(fā)生向上轉(zhuǎn)型的時(shí)機(jī)】
- 直接賦值
- 方法傳參
- 函數(shù)的返回值
public class TestAnimal {
// 2. 函數(shù)傳參:形參為父類(lèi)引用,可以接收任意子類(lèi)的對(duì)象
public static void eatFood(Animal a) {
a.eat();
}
// 3. 作返回值:返回任意子類(lèi)對(duì)象
public static Animal buyAnimal(String var) {
if ("狗" == var) {
return new Dog("狗狗", 1);
} else if ("貓" == var) {
return new Cat("貓貓", 1);
} else {
return null;
}
}
public static void main(String[] args) {
Animal cat = new Cat("元寶", 2); // 1. 直接賦值:子類(lèi)對(duì)象賦值給父類(lèi)對(duì)象
Dog dog = new Dog("小七", 1);
}
}優(yōu)缺點(diǎn):
- 優(yōu)點(diǎn):讓代碼更加靈活
- 缺點(diǎn):不能訪問(wèn)到子類(lèi)特有的方法
2、重寫(xiě)
函數(shù)名相同、參數(shù)列表相同、返回值相同或是【協(xié)變類(lèi)型】(父子類(lèi)關(guān)系)
【方法重寫(xiě)的規(guī)則】
- 重寫(xiě)的方法訪問(wèn)權(quán)限不能比父類(lèi)中原方法的的權(quán)限低;
- 父類(lèi)中被static、private、final修飾的方法、構(gòu)造方法不能被重寫(xiě);
- 重寫(xiě)的方法,可以使用 @override 注解來(lái)顯示指定(幫助我們進(jìn)行一些合法性的檢驗(yàn))。比如方法名拼寫(xiě)錯(cuò)誤,編譯會(huì)報(bào)錯(cuò);
- 重寫(xiě)的返回值類(lèi)型可以不同,但是必須具有父子關(guān)系。
- 被final修飾的方法,叫做密封方法,該方法不能被重寫(xiě)。
- 外部類(lèi)只能是public或者默認(rèn)權(quán)限
【動(dòng)態(tài)綁定和靜態(tài)綁定】
- 動(dòng)態(tài)綁定:發(fā)生的條件(1、父類(lèi)引用引用子類(lèi)對(duì)象;2、通過(guò)父類(lèi)引用,可以訪問(wèn)到子類(lèi)中的方法)。后期綁定,即在編譯時(shí)不能確定方法的行為,需要等到程序運(yùn)行時(shí),才能夠確定調(diào)用哪個(gè)類(lèi)的方法;
- 靜態(tài)綁定:前期綁定,編譯時(shí),根據(jù)用戶(hù)傳遞的參數(shù)類(lèi)型確定具體的調(diào)用方法(函數(shù)重載)
3、多態(tài)
一個(gè)引用調(diào)用同一個(gè)方法,可以表現(xiàn)出不同的形式,這種思想稱(chēng)為多態(tài)。在父類(lèi)的構(gòu)造方法中不要調(diào)用重寫(xiě)的方法。
【多態(tài)實(shí)現(xiàn)的條件】
- 必須在繼承條件下
- 子類(lèi)對(duì)父類(lèi)方法進(jìn)行重寫(xiě)
- 通過(guò)父類(lèi)引用調(diào)用重寫(xiě)的方法
- 發(fā)生了向上轉(zhuǎn)型
public class Animal(){
String name;
int age;
public Animal(String name, int age){
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(name + "吃飯");
}
}
public class Cat extends Animal{
public Cat(String name, int age){
super(name, age);
}
@Override
public void eat(){
System.out.println(name+"吃魚(yú)~~~");
}
}
public class Dog extends Animal {
public Dog(String name, int age){
super(name, age);
}
@Override
public void eat(){
System.out.println(name+"吃骨頭~~~");
}
}
public class TestAnimal {
// 編譯器在編譯代碼時(shí),并不知道要調(diào)用Dog 還是 Cat 中eat的方法
// 等程序運(yùn)行起來(lái)后,形參a引用的具體對(duì)象確定后,才知道調(diào)用那個(gè)方法
// 注意:此處的形參類(lèi)型必須時(shí)父類(lèi)類(lèi)型才可以
public static void eat(Animal a){
a.eat();
}
public static void main(String[] args) {
Animal animal1 = new Cat("元寶",2);
Animal animal2 = new Dog("小七", 1);
eat(animal1);
eat(animal2);
}
}【注】Java中所有的類(lèi)默認(rèn)繼承Object類(lèi)
到此這篇關(guān)于Java 繼承與多態(tài)超詳細(xì)梳理的文章就介紹到這了,更多相關(guān)Java 繼承與多態(tài)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java面向?qū)ο笾畬W(xué)生信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java面向?qū)ο笾畬W(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03
一文詳解Spring的Enablexxx注解使用實(shí)例
這篇文章主要為大家介紹了一文詳解Spring的Enablexxx注解使用實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Java基礎(chǔ)知識(shí)精通塊作用域與條件及switch語(yǔ)句
塊(block,即復(fù)合語(yǔ)句)是指由若干條 Java 語(yǔ)句組成的語(yǔ)句,并由一對(duì)大括號(hào)括起來(lái)。塊確定了變量的作用域。一個(gè)塊可以嵌套在另一個(gè)塊中;條件語(yǔ)句、switch語(yǔ)句是我們常見(jiàn)會(huì)用到的結(jié)構(gòu),感興趣的朋友來(lái)看看吧2022-04-04
基于MockMvc進(jìn)行springboot調(diào)試(SpringbootTest)
這篇文章主要介紹了基于MockMvc進(jìn)行springboot調(diào)試(SpringbootTest),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
Java中Lambda表達(dá)式和函數(shù)式接口的使用和特性
Java Lambda表達(dá)式是一種函數(shù)式編程的特性,可簡(jiǎn)化匿名內(nèi)部類(lèi)的寫(xiě)法,與函數(shù)式接口搭配使用,實(shí)現(xiàn)代碼簡(jiǎn)潔、可讀性高、易于維護(hù)的特點(diǎn),適用于集合操作、多線(xiàn)程編程等場(chǎng)景2023-04-04
深入理解JavaWeb中過(guò)濾器與監(jiān)聽(tīng)器的應(yīng)用
這篇文章主要介紹了JavaWeb中過(guò)濾器與監(jiān)聽(tīng)器的應(yīng)用,過(guò)濾器能夠?qū)ζヅ涞恼?qǐng)求到達(dá)目標(biāo)之前或返回響應(yīng)之后增加一些處理代碼,監(jiān)聽(tīng)器是一個(gè)接口內(nèi)容由我們實(shí)現(xiàn),會(huì)在特定時(shí)間被調(diào)用,感興趣想要詳細(xì)了解可以參考下文2023-05-05

