亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java 繼承和多態(tài)的作用及好處

 更新時(shí)間:2025年06月23日 14:47:53   作者:蘇小瀚  
文章講解Java繼承與多態(tài)的概念、語(yǔ)法及應(yīng)用,繼承通過(guò)extends復(fù)用父類成員,減少冗余;多態(tài)實(shí)現(xiàn)方法重寫與向上轉(zhuǎn)型,提升靈活性與代碼復(fù)用性,動(dòng)態(tài)綁定降低圈復(fù)雜度,感興趣的朋友一起看看吧

1. 繼承

1.1 什么是繼承

生活中有很多繼承的例子,如兒子繼承父親的家產(chǎn),學(xué)弟繼承學(xué)長(zhǎng)的宿舍等,而在Java中繼承就是子類繼承了父類里面的成員,也就相當(dāng)于在父類的基礎(chǔ)上進(jìn)行拓展的內(nèi)容放到子類里面,從簡(jiǎn)單到復(fù)雜的過(guò)程,而Java里面的繼承是通過(guò)extends關(guān)鍵字實(shí)現(xiàn)的。

1.2 繼承的作用和好處

當(dāng)有兩個(gè)類dog類和cat類如下:

public class Dog {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name + "在吃東西");
    }
    public void map() {
        System.out.println(this.name + "在喵喵叫");
    }
}
public class Cat {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name + "在吃東西");
    }
    public void wap() {
        System.out.println(this.name + "在汪汪叫");
    }
}

通過(guò)觀察會(huì)發(fā)現(xiàn)上面的dog類和cat類里面有一些共有的成員變量和方法,這時(shí)候我們就在想能不能把這些元素放到同一個(gè)類里面被其他需要的類使用呢?

這時(shí)候就想到了繼承,繼承就可以實(shí)現(xiàn)這一需求,這時(shí)我們?cè)賱?chuàng)建一個(gè)類:

public class Test {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name + "在吃東西");
    }
}

此時(shí)我們就可以通過(guò)關(guān)鍵字extends來(lái)實(shí)現(xiàn)將Test類里面的成員用到dog和cat類中。

而通過(guò)繼承可以減少代碼的復(fù)用。

1.3 繼承的語(yǔ)法

修飾符 class 子類 extends 父類 { }

上面的cat和dog類就可以通過(guò)extends關(guān)鍵字實(shí)現(xiàn)繼承,如下圖:

public class Dog extends Test {
    public void map() {
        System.out.println(this.name + "在喵喵叫");
    }
}
public class Cat extends Test {
    public void wap() {
        System.out.println(this.name + "在汪汪叫");
    }
}

此時(shí)dog類和cat類就包含了父類里面的成員,在內(nèi)存里也就是:

1.4 子類訪問(wèn)父類里面的成員變量

1. 子類和父類里面的成員變量不同名 

這時(shí)候可以直接訪問(wèn):

//父類
public class Base {
    int a;
    int b;
}
//子類
public class Derived extends Base {
    int c;
    public void test() {
        a = 10;
        b = 20;
        c = 30;
    }
}

子類可以直接使用this訪問(wèn)子類和父類中的成員變量。

2. 子類和父類中存在成員變量同名

//父類
public class Base {
    int a;
    int b;
}
//子類
public class Derived extends Base {
    int c;
    int a;
    public void test() {
        a = 10;
        b = 20;
        c = 30;
    }
}

此時(shí)父類和子類都有成員變量a,此時(shí)子類會(huì)優(yōu)先訪問(wèn)子類的變量。

  • 當(dāng)子類和父類有相同名字的成員變量時(shí)候時(shí)候,會(huì)優(yōu)先訪問(wèn)子類的成員變量。
  • 若子類和父類都沒(méi)有的成員變量訪問(wèn)則會(huì)編譯錯(cuò)誤。

1.5 子類訪問(wèn)父類里面的成員方法 

1. 子類和父類方法名字不同。

則子類直接訪問(wèn)訪問(wèn)父類的方法。并且子類和父類的方法可以構(gòu)成方法的重載,如下面代碼:

public class Base {
    public void sit() {
        System.out.println("hehe");
    }
}
public class Derived extends Base {
    public void print() {
        System.out.println("haha");
    }
    public void sit(int a) {
        System.out.println("hehe");
    }
    public void test() {
        print();//調(diào)用子類的方法
        //構(gòu)成重載
        sit();//調(diào)用父類的方法
        sit(10);//調(diào)用子類的方法
    }
}

當(dāng)子類和父類的方法相同時(shí),則子類調(diào)用父類時(shí),則會(huì)就近原則優(yōu)先調(diào)用子類。代碼如下:

public class Base {
    public void sit() {
        System.out.println("hehe");
    }
}
public class Derived extends Base {
    public void print() {
        System.out.println("haha");
    }
    public void sit() {
        System.out.println("haha");
    }
    public void test() {
        print();//調(diào)用子類的方法
        sit();//子類和父類都有該方法會(huì)優(yōu)先調(diào)用子類的方法,會(huì)打印haha。
    }
}

1.6 super關(guān)鍵字

上面我們發(fā)現(xiàn)子類和父類當(dāng)中如果出現(xiàn)相同的成員變量或者成員方法時(shí),子類調(diào)用該成員時(shí)會(huì)優(yōu)先調(diào)用子類的成員,那如何調(diào)用父類的成員呢?

這里就要用到super關(guān)鍵字了,super關(guān)鍵字就是用來(lái)在子類中調(diào)用父類的成員的,當(dāng)子類和父類有相同的成員時(shí),就使用super關(guān)鍵字區(qū)分。

super關(guān)鍵字用于子類調(diào)用父類成員變量:

下面代碼可以發(fā)現(xiàn)當(dāng)子類和父類都有同一個(gè)成員變量a時(shí),就可以通過(guò)super關(guān)鍵字來(lái)調(diào)用父類的成員變量a,當(dāng)然this既可以調(diào)用子類里面的成員變量,又可以調(diào)用父類的成員變量,只有子類和父類有相同名字成員變量時(shí),才用super加以區(qū)分。

public class Base {
    int a;
    int b;
}
public class Derived extends Base {
    int a;
    int c;
    public void test1() {
        this.a = 10;//this調(diào)用的父類的成員變量。
        super.a = 20;//super調(diào)用的子類的成員變量。
        this.b = 40;//this調(diào)用的子類的成員變量。
    }
}

在堆區(qū)里是這樣的:

super關(guān)鍵字用于子類調(diào)用父類成員方法:

這里和成員變量一樣,用super關(guān)鍵字來(lái)區(qū)分相同的成員方法,這里的成員方法支持方法的重載:

public class Base {
    public void print() {
        System.out.println("nihao");
    }
    public void sit() {
        System.out.println("hehe");
    }
}
public class Derived extends Base {
    public void print() {
        System.out.println("buhao");
    }
    public void sit(int a) {
        System.out.println("hehe");
    }
    public void test() {
        this.print();//調(diào)用子類的方法
        super.print();//調(diào)用父類的方法
        //構(gòu)成重載
        this.sit();//調(diào)用父類的方法
        this.sit(10);//調(diào)用子類的方法
    }
}

 super關(guān)鍵字用于調(diào)用構(gòu)造方法:

當(dāng)父類有構(gòu)造方法的時(shí)候,子類也必須有構(gòu)造方法,因?yàn)樽宇愐ㄟ^(guò)super關(guān)鍵字先調(diào)用父類的構(gòu)造方法,再設(shè)置自己的成員方法,并且通過(guò)super(父類的構(gòu)造方法名)的形式調(diào)用,并且必須放在構(gòu)造方法的第一行。所以super和this不能共用,代碼如下:

public class Base {
    int a;
    int b;
    //父類的構(gòu)造方法
    public Base(int a, int b) {
        this.a = a;
        this.b = b;
    }
}
public class Derived extends Base {
    int c;
    int d;
    //子類的構(gòu)造方法
    public Derived(int a, int b, int c, int d) {
        super(a,b);//第一行先調(diào)用父類的構(gòu)造方法
        this.c = c;
        this.d = d;
    }
}

當(dāng)子類和父類都沒(méi)有構(gòu)造方法是,Java中提供了隱藏的構(gòu)造方法在子類和父類中。

當(dāng)父類中定義了無(wú)參的 構(gòu)造方法時(shí),子類的構(gòu)造方法第一行不寫調(diào)用父類的代碼時(shí),Java也會(huì)隱藏的在第一行寫上該代碼,但如果是有參的,則需要自己書寫。

1.7 this和super

相同:

  • 都不能在靜態(tài)方法中使用。
  • 都是關(guān)鍵字。
  • 在構(gòu)造方法中調(diào)用時(shí)必須是第一條語(yǔ)句。

不同:

  • this是對(duì)當(dāng)前對(duì)象的成員調(diào)用,而super是對(duì)從父類中繼承下來(lái)的成員的調(diào)用。
  • 在構(gòu)造方法中,this用于對(duì)本類構(gòu)造方法的訪問(wèn),而super是對(duì)父類的構(gòu)造方法的訪問(wèn)。兩者不能同時(shí)存在。

1.8 繼承關(guān)系上的調(diào)用順序

我們之前說(shuō)過(guò),在初始化成員變量時(shí),在實(shí)例化一個(gè)類時(shí),調(diào)用優(yōu)先級(jí)是:靜態(tài)代碼塊>實(shí)例代碼塊>構(gòu)造方法。

而在同時(shí)調(diào)用一個(gè)繼承父類的子類和該父類時(shí),調(diào)用優(yōu)先級(jí)是:父類的靜態(tài)代碼塊優(yōu)于子類的靜態(tài)代碼塊,父類的實(shí)例和構(gòu)造優(yōu)于子類的實(shí)例和構(gòu)造,而在第二次實(shí)例化對(duì)象時(shí),靜態(tài)初始化不再調(diào)用,因?yàn)轭愔患虞d一次。

1.8 protected

我們知道protected是訪問(wèn)限定符,而它修飾的變量使用的范圍是同一包下的都可以訪問(wèn),再加上不同包下的子類可以訪問(wèn),代碼如下:

這里變量d是用protected修飾的在demo2包里,而在demo3里面繼承Base,可以調(diào)用d變量。

package demo2;
public class Base {
    protected int d;
}
package demo3;
import demo2.Base;
public class Derived extends Base {
    public void test() {
        super.d = 20;
    }
}

1.9 繼承方式

Java里面提供了以下繼承方式:

單繼承:就是A 繼承 B。

多層繼承:A 繼承 B ,B 繼承 C

不同類繼承同一個(gè)類,A 繼承 C,B 繼承 C;

但是不支持一個(gè)類繼承多個(gè)類:A 繼承 B, A 繼承 C;這種是錯(cuò)誤的繼承方式。

1.10 final關(guān)鍵字

finai關(guān)鍵字有三種用法:

1. 密封類 當(dāng)一個(gè)類被final修飾后,則該類不能再被其他的類繼承了。

2.修飾變量:final修飾變量后該變量就變成常量了。

3.密封成員方法:表示該方法不能被重寫。

1.11 組合

        組合就是說(shuō)對(duì)象之間是包含關(guān)系,它可以把類與類之間分開(kāi)成獨(dú)立的個(gè)體,需要的時(shí)候相互調(diào)用,不同于繼承的思想,當(dāng)父類改變時(shí)一定會(huì)影響子類,相當(dāng)于汽車這個(gè)對(duì)象是由輪胎,發(fā)動(dòng)機(jī)等對(duì)象組成的,而汽車這個(gè)類里面可以調(diào)用輪胎和發(fā)動(dòng)機(jī)類里面的一些屬性和方法來(lái)使用,如果這時(shí)加入一個(gè)電池類,但是油車沒(méi)有電池,電車才有,如果是繼承關(guān)系那么油車就不能繼承Car這個(gè)類了,但如果是組合思想,電車就可以單獨(dú)調(diào)用這個(gè)電池類。

class Tire {
    //輪胎類
}
class Engine {
    //發(fā)動(dòng)機(jī)類
}
public class Car {
    public Tire tire;
    public Engine engine;
}

2. 多態(tài)

2.1 方法的重寫

       方法的重寫是在繼承的條件下,子類對(duì)父類的方法進(jìn)行重寫,子類重寫的方法,返回值類型,方法名,參數(shù)都完全相同,并且子類的訪問(wèn)修飾符的范圍要大于等于父類的訪問(wèn)修飾符的范圍。

      當(dāng)然參數(shù)之間也可以不用相同,參數(shù)之間構(gòu)成父子類關(guān)系也可以實(shí)現(xiàn)方法的重寫,這種叫做協(xié)變類型。

可以使用@Override來(lái)判斷該方法是否重寫,如果重寫錯(cuò)誤,還會(huì)顯示報(bào)錯(cuò)。

private修飾的方法,構(gòu)造方法,靜態(tài)方法,final修飾的方法等都能重寫。

下面代碼中,Cat繼承Animal,子類對(duì)父類的eat方法進(jìn)行了重寫。

public class Animal{
    public String name;
    public int age;
    public Animal() {
    }
    public void eat() {
        System.out.println("正在吃食物");
    }
}
public class Cat extends Animal{
    public Cat() {
        super();
    }
    @Override
    public void eat() {
        System.out.println("正在吃貓糧");
    }
}

 2.2 向上轉(zhuǎn)型

向上轉(zhuǎn)型就是父類的引用指向子類的對(duì)象。下面代碼父類Animal引用指向子類Cat對(duì)象。

Animal animal = new Cat();
animal.eat();

這時(shí)候父類的引用可以調(diào)用父類的成員,但是只能調(diào)用子類重寫父類的方法,子類的其他成員都不能調(diào)用。

常見(jiàn)的向上轉(zhuǎn)型的方式:

  • 直接賦值
  • 參數(shù)傳遞
  • 返回值傳遞

2.3 動(dòng)態(tài)綁定和靜態(tài)綁定

        動(dòng)態(tài)綁定就是,在父類的引用調(diào)用重寫的方法時(shí),編譯過(guò)程調(diào)用的是父類的方法,但在運(yùn)行時(shí)綁定的卻是子類的方法,最后運(yùn)行結(jié)果調(diào)用的是子類的方法。

        這是因?yàn)樵贘ava虛擬機(jī)中存在一塊空間為方法區(qū),這里的每個(gè)方法都綁定一個(gè)地址,在運(yùn)行時(shí)父類方法綁定的地址變?yōu)樽宇惙椒ń壎ǖ牡刂罚哉{(diào)用的子類的方法。

動(dòng)態(tài)綁定的條件 :

  • 發(fā)生向上轉(zhuǎn)型
  • 存在方法的重寫
  • 父類引用調(diào)用了重寫的方法

靜態(tài)綁定是在編譯時(shí)候綁定的,比如說(shuō)方法的重載,根據(jù)參數(shù)來(lái)選擇調(diào)用的方法。

2.4 多態(tài)

多態(tài)就是同一種類型的引用調(diào)用同一種方法,該引用所指的對(duì)象不同,得到的結(jié)果也不同。

下面代碼中,父類的引用分別指向子類Bird和子類Cat,都調(diào)用eat方法,產(chǎn)生的結(jié)果也不相同,這就是多態(tài)。

public class Animal{
    public String name;
    public int age;
    public Animal() {
    }
    public void eat() {
        System.out.println("正在吃食物");
    }
}
public class Cat extends Animal{
    public Cat() {
        super();
    }
    @Override
    public void eat() {
        System.out.println("正在吃貓糧");
    }
}
public class Bird exteends Animal {
    public Bird() {
        super();
    }
    @Override
    public void eat() {
        System.out.println("正在吃鳥(niǎo)糧");
    }
    public void fly() {
        System.out.println("正在飛");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal1 = new Cat();
        animal1.eat();
        Animal animal2 = new Bird();
        animal2.eat();
    }
}

結(jié)果:

 多態(tài)產(chǎn)生的條件:

  • 子類對(duì)父類的方法進(jìn)行重寫
  • 繼承的條件下
  • 通過(guò)父類的引用調(diào)用子類的重寫的方法。

2.5 向下轉(zhuǎn)型

向下轉(zhuǎn)型就是說(shuō)將父類引用的類型強(qiáng)制類型轉(zhuǎn)換為子類的類型。

    Animal animal = new Cat();
    Cat cat = (Cat)animal;

向下轉(zhuǎn)型后,就可以調(diào)用子類的成員。

        但是如果父類引用所指的對(duì)象的類型,與強(qiáng)制類型轉(zhuǎn)換的類型不一樣就會(huì)編譯報(bào)錯(cuò),產(chǎn)生ClassCastExceprion(類型轉(zhuǎn)換異常),所以向上轉(zhuǎn)型也不太安全,所以不經(jīng)常使用。

為了解決這種安全性,Java引入了關(guān)鍵字 instanceof 用來(lái)判斷強(qiáng)制類型轉(zhuǎn)換是否安全。

        Animal animal = new Cat();
        if(animal instanceof Cat) {
            Cat cat = (Cat)animal;
        }else {
            System.out.println("不安全");
        }

2.6 圈復(fù)雜度

圈復(fù)雜度是用來(lái)描述代碼的復(fù)雜程度的,一般跟條件語(yǔ)句和循環(huán)語(yǔ)句的數(shù)量有關(guān),而多態(tài)就可以很好的解決圈復(fù)雜度過(guò)大的問(wèn)題。

假設(shè)要打印形狀,就可以利用多態(tài)來(lái)實(shí)現(xiàn):

public class Shape {
    public Shape() {
    }
    public void print() {
        System.out.println("畫一個(gè)圖案");
    }
}
public class Rect extends Shape {
    public Rect() {
        super();
    }
    public void print() {
        System.out.println("畫一個(gè)矩形");
    }
}
public class Cycle extends Shape {
    public Cycle() {
        super();
    }
    public void print() {
        System.out.println("畫一個(gè)圓形");
    }
}
public class Test {
    public static void drawShapes(Shape shape) {
        shape.print();
    }
    public static void main(String[] args) {
        Rect rect = new Rect();
        Cycle cycle = new Cycle();
        Shape[] shapes = {rect,cycle,rect,cycle};
        for(Shape shape : shapes) {
            drawShapes(shape);
        }
    }
}

打印結(jié)果如下:

利用多態(tài)實(shí)現(xiàn)的代碼的圈復(fù)雜度相對(duì)來(lái)說(shuō)就很低。

注意:盡量不要在構(gòu)造方法中調(diào)用重寫的方法,構(gòu)造方法也支持動(dòng)態(tài)綁定。減少使用實(shí)例化的方法。否則可能會(huì)出現(xiàn)問(wèn)題??梢允褂胒inlal和private修飾的方法,它們不支持方法的重寫。 

到此這篇關(guān)于Java 繼承和多態(tài)的作用及好處的文章就介紹到這了,更多相關(guān)Java 繼承和多態(tài)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java設(shè)計(jì)模式詳解之門面模式(外觀模式)

    Java設(shè)計(jì)模式詳解之門面模式(外觀模式)

    為子系統(tǒng)中的一組接口提供一個(gè)一致的界面, Facade 模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。本文給大家介紹Java設(shè)計(jì)模式詳解之門面模式(外觀模式),感興趣的朋友參考下吧
    2016-04-04
  • 如何創(chuàng)建SpringBoot項(xiàng)目

    如何創(chuàng)建SpringBoot項(xiàng)目

    這篇文章主要介紹了如何創(chuàng)建SpringBoot項(xiàng)目,幫助大家更好的學(xué)習(xí)和使用springboot框架,感興趣的朋友可以了解下
    2021-01-01
  • Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解

    Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解

    這篇文章主要為大家介紹了Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Mybatis如何分割字符串

    Mybatis如何分割字符串

    這篇文章主要介紹了Mybatis如何分割字符串問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • IDEA 創(chuàng)建一個(gè)Mybatis Maven項(xiàng)目的方法步驟(圖文)

    IDEA 創(chuàng)建一個(gè)Mybatis Maven項(xiàng)目的方法步驟(圖文)

    這篇文章主要介紹了IDEA 創(chuàng)建一個(gè)Mybatis Maven項(xiàng)目的方法步驟(圖文),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 利用java制作一個(gè)小的目錄查詢器的方法

    利用java制作一個(gè)小的目錄查詢器的方法

    下面小編就為大家?guī)?lái)一篇利用java制作一個(gè)小的目錄查詢器的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • java使用RSA加密方式實(shí)現(xiàn)數(shù)據(jù)加密解密的代碼

    java使用RSA加密方式實(shí)現(xiàn)數(shù)據(jù)加密解密的代碼

    這篇文章給大家分享java使用RSA加密方式實(shí)現(xiàn)數(shù)據(jù)加密解密,通過(guò)實(shí)例代碼文字相結(jié)合給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下
    2019-11-11
  • Java 在PPT中添加文本和圖片超鏈接的實(shí)現(xiàn)方法

    Java 在PPT中添加文本和圖片超鏈接的實(shí)現(xiàn)方法

    這篇文章主要介紹了Java 在PPT中添加文本和圖片超鏈接的實(shí)現(xiàn)方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 關(guān)于maven下載慢的問(wèn)題

    關(guān)于maven下載慢的問(wèn)題

    這篇文章主要介紹了關(guān)于maven下載慢的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 基于Jpa中ManyToMany和OneToMany的雙向控制

    基于Jpa中ManyToMany和OneToMany的雙向控制

    這篇文章主要介紹了Jpa中ManyToMany和OneToMany的雙向控制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12

最新評(píng)論