最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多態(tài)的全面系統(tǒng)解析

 更新時間:2022年03月02日 15:41:45   作者:最愛吃魚罐頭  
多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發(fā)出的方法調(diào)用在編程時并不確定,而是在程序運(yùn)行期間才確定,即一個引用變量到底會指向哪個類的實(shí)例對象,該引用變量發(fā)出的方法調(diào)用到底是哪個類中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定

茫茫人海千千萬萬,感謝這一秒你看到這里。希望我的能對你的有所幫助!共勉!

愿你在未來的日子,保持熱愛,奔赴山海!

Java基礎(chǔ)知識(多態(tài))

多態(tài)

因?yàn)樵诔绦蜻\(yùn)行時才確定具體的類,這樣,不用修改源程序代碼,就可以讓引用變量綁定到各種不同的類實(shí)現(xiàn)上,從而導(dǎo)致該引用調(diào)用的具體方法隨之改變,即不修改程序代碼就可以改變程序運(yùn)行時所綁定的具體代碼,讓程序可以選擇多個運(yùn)行狀態(tài),這就是多態(tài)性。

多態(tài)的定義和存在的必要條件

多態(tài)的定義:

  • 多態(tài)是指同一個行為具有多個不同表現(xiàn)形式或形態(tài)的能力。
  • 多態(tài)就是同一個接口,使用不同的實(shí)例而執(zhí)行不同操作。

就舉動物類的例子吧,cat和dog都是屬于動物這一類,而動物呢,都有一個共同的行為就是吃??吧,而不同的動物所吃的食物都大不相同吧!

呢,它喜歡吃魚!

而對于狗呢,它就比較喜歡啃骨頭!

所以多態(tài)就是對于吃這一行為來說,每種動物對吃這一行為所表現(xiàn)的行為都不盡相同。

多態(tài)存在的三個必要條件

  • 繼承或者實(shí)現(xiàn)

在多態(tài)中必須存在有繼承或者實(shí)現(xiàn)關(guān)系的子類和父類。

  • 方法的重寫

子類對父類中某些方法進(jìn)行重新定義(重寫),在調(diào)用這些方法時就會調(diào)用子類的方法。

  • 基類引用指向派生類對象,即父類引用指向子類對象

父類類型:指子類對象繼承的父類類型,或者實(shí)現(xiàn)的父接口類型。

?多態(tài)的格式:

父類類型 變量名 = new 子類類型();

變量名.方法名();

多態(tài)格式可以充分體現(xiàn)了同一個接口,使用不同的實(shí)例而執(zhí)行不同操作。

接下來我們具體來進(jìn)行案例體會體會吧!??????

多態(tài)的案例

多態(tài)我們首先要知道的一點(diǎn):

當(dāng)使用多態(tài)方式調(diào)用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,執(zhí)行的是子類重寫后方法。如果子類沒有重寫該方法,就會調(diào)用父類的該方法。

總結(jié)起來就是:編譯看左邊??,運(yùn)行看右邊。??

首先我們先定義一個父類動物類,動物有吃的行為!

接著定義一個貓類和狗類去繼承動物類,重寫里面的吃行為!

??具體代碼如下:

定義動物父類:

package com.nz.pojo;

/**
 * 先定義一個父類 --> 動物類
 * 動物都有一個吃的行為屬性
 */
public class Animal {

    public void eat() {
        System.out.println("動物它們都會吃東西?。?!");
    }
}

定義貓咪子類:

package com.nz.pojo;

/**
 * 定義貓類繼承動物類,
 * 隨之重寫里面的吃行為,因?yàn)樨堃灿谐缘男袨椋秦埾矚g吃罐頭
 */
public class Cat extends Animal{

    public void eat() {
        System.out.println("小喵咪都喜歡吃魚罐頭!");
    }
}

定義小狗子類:

package com.nz.pojo;

/**
 * 定義狗類繼承動物類,
 * 隨之重寫里面的吃行為,因?yàn)楣芬灿谐缘男袨椋枪废矚g啃骨頭
 */
public class Dog extends Animal{

    public void eat() {
        System.out.println("小狗狗都愛啃骨頭!");
    }
}

定義測試類,測試多態(tài)的形式:

package com.nz;

import com.nz.pojo.Animal;
import com.nz.pojo.Cat;
import com.nz.pojo.Dog;

/**
 * 測試多態(tài)的形式
 */
public class Demo {
    public static void main(String[] args) {

        // 多態(tài)形式,創(chuàng)建貓類對象
        Animal animal = new Cat();
        // 調(diào)用的是Cat的 eat
        animal.eat();

        // 多態(tài)形式,創(chuàng)建狗類對象
        Animal animal2 = new Dog();
        // 調(diào)用的是Dog的eat
        animal2.eat();
    }
}

得到的結(jié)果:

小喵咪都喜歡吃魚罐頭!
小狗狗都愛啃骨頭!

類的大致結(jié)構(gòu):

可以看出我們可以使用多態(tài)的屬性得到不同的動物的一個吃的行為屬性!

多態(tài)的好處

提高了代碼的拓展性,使用父類類型作為方法形式參數(shù),傳遞子類對象給方法,進(jìn)行方法的調(diào)用。

具體我們來看看吧:

繼續(xù)使用上述的動物類、貓類、狗類吧。

定義測試類:

package com.nz;

import com.nz.pojo.Animal;
import com.nz.pojo.Cat;
import com.nz.pojo.Dog;

/**
 * 測試多態(tài)的好處
 */
public class Demo2 {
    public static void main(String[] args) {
        // 創(chuàng)建貓和狗對象
        Cat cat = new Cat();
        Dog dog = new Dog();

        // 調(diào)用catEat
        catEat(cat);
        // 調(diào)用dogEat
        dogEat(dog);

		/*
        多態(tài)的好處:
            以上各個動物的吃的方法, 我們都可以使用animalEat(Animal a)方法來代替。
            并且執(zhí)行效果都一樣, 所以我們可以使用animalEat直接替代了不同動物的吃方法。
        */
        animalEat(cat);
        animalEat(dog);
    }

    /*
        定義幾個不同吃的方法,看看具體調(diào)用后的結(jié)果是什么吧!
     */
    public static void catEat (Cat cat){
        cat.eat();
    }

    public static void dogEat (Dog dog){
        dog.eat();
    }

    public static void animalEat (Animal animal){
        animal.eat();
    }
}

執(zhí)行結(jié)果:

小喵咪都喜歡吃魚罐頭!
小狗狗都愛啃骨頭!
小喵咪都喜歡吃魚罐頭!
小狗狗都愛啃骨頭!

可以看出,由于多態(tài)的特性,我們的animalEat()方法傳入的Animal類型參數(shù),并且它是我們的Cat和Dog的父類類型,父類類型接收子類對象,所以我們可以將Cat對象和Dog對象,傳遞給animalEat()方法。

所以我們可以完全使用animalEat()方法來替代catEat()方法和dogEat()方法,達(dá)到同樣的效果!以至于我們可以不必再單獨(dú)寫xxxEat()方法來傳入指定的動物參數(shù)了,從而實(shí)現(xiàn)了實(shí)現(xiàn)類的自動切換。

所以多態(tài)的好處體現(xiàn)在:可以使我們的程序編寫的更簡單,并有良好的擴(kuò)展性。

多態(tài)的弊端

從上面的多態(tài)的好處,可以看到我們可以使用父類的參數(shù)代替了某個子類的參數(shù),從而達(dá)到程序的擴(kuò)展!

但是對于某個子類有些獨(dú)有的功能方法時,此時我們的多態(tài)的寫法就無法訪問子類獨(dú)有功能了。

具體來瞧瞧?

代碼如下:

重新定義下貓的子類:

package com.nz.pojo;

/**
 * 定義貓類繼承動物類,
 * 隨之重寫里面的吃行為,因?yàn)樨堃灿谐缘男袨?,但是貓喜歡吃罐頭
 */
public class Cat extends Animal{

    public void eat() {
        System.out.println("小喵咪都喜歡吃魚罐頭!");
    }

    /**
     * 增加一哥貓咪特有的玩球方法()
     */
    public void playBall() {
        System.out.println("小喵咪都喜歡小球!");
    }
}

定義測試類:

package com.nz;

import com.nz.pojo.Animal;
import com.nz.pojo.Cat;

/**
 * 測試多態(tài)的弊端!
 */
public class Demo3 {
    public static void main(String[] args) {
        Animal animal = new Cat();

        animal.eat();

        animal.playBall();//編譯報錯,編譯看左邊,Animal沒有這個方法
    }
}

可以看到動物類和貓類有個共同的eat吃方法,但是呢,貓咪多了個玩球球的方法。而對于動物對象來說,它本身動物類沒有玩球球的方法,所以它的編譯就直接沒有通過了!

那有什么方法解決呢?且看下一章節(jié)吧!

引用類型轉(zhuǎn)換

1. 引用類型轉(zhuǎn)換是什么,為什么需要它?

從上面的多態(tài)的弊端的案例中,我們可以看到,我們使用動物對象時無法直接訪問到貓類中的玩球球方法,這也就是我們之前說的編譯看左邊,運(yùn)行看右邊。

而在我們使用多態(tài)方式調(diào)用方法時,首先檢查會左邊的父類中是否有該方法,如果沒有,則編譯錯誤。也就代表著,父類無法調(diào)用子類獨(dú)有的方法。、

所以說,如果編譯都錯誤,更別說運(yùn)行了。這也是多態(tài)給我們帶來的一點(diǎn)小困擾,而我們?nèi)绻胍{(diào)用子類特有的方法,必須做向下轉(zhuǎn)型。

2. 向上轉(zhuǎn)型(自動轉(zhuǎn)換)

對于向下轉(zhuǎn)型,我們先來講解下向上轉(zhuǎn)型的概念吧。

向上轉(zhuǎn)型:

多態(tài)本身是子類向父類向上轉(zhuǎn)換(自動轉(zhuǎn)換)的過程,這個過程是默認(rèn)的。當(dāng)父類引用指向一個子類對象時,便是向上轉(zhuǎn)型。

對于父類和子類的關(guān)系來說,具體來看圖說話:

父類相對與子類來說是大范圍的類型,Animal是動物類,是父類。而Cat是貓咪類,是子類。

所以對于父類Animal來說,它的范圍是比較大的,它包含一切動物,包括貓咪類和小狗類。

所以對于子類類型這種范圍小的,我們可以直接自動轉(zhuǎn)型給父類類型的變量。

使用格式:

父類類型 變量名 = new 子類類型();

如:Animal animal = new Cat();

相當(dāng)于有:
Animal animal = (Animal) new Cat();

相當(dāng)于自動幫我們了一個隱形的轉(zhuǎn)換為動物類的一個過程,因?yàn)閯游锉旧砭桶素堖洹?/p>

3. 向下轉(zhuǎn)型(強(qiáng)制轉(zhuǎn)換)

向上轉(zhuǎn)型可以知道它是子類自動轉(zhuǎn)換為父類的一個過程,所以我們現(xiàn)在再來看看向下轉(zhuǎn)型的定義:

向下轉(zhuǎn)型:

向下轉(zhuǎn)型就是由父類向子類向下轉(zhuǎn)換的過程,這個過程是強(qiáng)制的。一個需要將父類對象轉(zhuǎn)為子類對象,可以使用強(qiáng)制類型轉(zhuǎn)換的格式,這便是向下轉(zhuǎn)型。

為什么這種就必須自己強(qiáng)制加上一個類型轉(zhuǎn)換過程呢?

對于父類和子類的關(guān)系來說,我們接著看圖說話:

對于貓咪類的話,它在動物類中只是其中的一部分吧,而對于動物類來說,它有許多其他子類動物如狗,牛,豬等等。

所以對于動物父類想要向下轉(zhuǎn)型的時候, 它此時不知道指向那個子類,因?yàn)椴淮_定呀,所以就必須自己加上強(qiáng)制的類型轉(zhuǎn)換的一個過程。

使用格式:

子類類型 變量名 = (子類類型) 父類變量名;
如:
Animal animal = new Cat();
Cat cat = (Cat) animal;
cat.playBall();// 此時我們就可以使用貓咪的特有方法啦

所以對于多態(tài)的弊端,無法使用子類特有的參數(shù),我們也解決啦,可以通過向下轉(zhuǎn)型的方法,從而將類型強(qiáng)制轉(zhuǎn)換為某個子類對象后,再去調(diào)用子類的特有方法!

4. 向下轉(zhuǎn)型的問題

雖然我們可以使用向下轉(zhuǎn)型使得我們可以使用子類的獨(dú)有方法,但是轉(zhuǎn)型的過程中,一不小心就會遇到這樣的問題了,來,我們來看看下面的代碼:

public class Test {
    public static void main(String[] args) {
        // 向上轉(zhuǎn)型  
        Animal a = new Cat();  
        a.eat();               // 調(diào)用的是 Cat 的 eat

        // 向下轉(zhuǎn)型  
        Dog d = (Dog)a;       
        d.watchHouse();        // 調(diào)用的是 Dog 的 watchHouse 【運(yùn)行報錯】
    }  
}

這段代碼可以通過編譯,但是運(yùn)行時,卻報出了 ClassCastException ,類型轉(zhuǎn)換異常!這是因?yàn)?,明明?chuàng)建了Cat類型對象,運(yùn)行時,當(dāng)然不能轉(zhuǎn)換成Dog對象的。

5. 轉(zhuǎn)型的異常

轉(zhuǎn)型的過程中,一不小心就會遇到這樣的問題,請看如下代碼:

定義狗類中額外的獨(dú)有遛狗方法:

package com.nz.pojo;

/**
 * 定義狗類繼承動物類,
 * 隨之重寫里面的吃行為,因?yàn)楣芬灿谐缘男袨椋枪废矚g啃骨頭
 */
public class Dog extends Animal{

    public void eat() {
        System.out.println("小狗狗都愛啃骨頭!");
    }

    public void walk() {
        System.out.println("小狗在被我溜著!");
    }
}

定義測試類

package com.nz;

import com.nz.pojo.Animal;
import com.nz.pojo.Cat;
import com.nz.pojo.Dog;

/**
 * 測試多態(tài)的向下轉(zhuǎn)型的問題
 */
public class Demo4 {
    public static void main(String[] args) {

        // 向上轉(zhuǎn)型的過程
        Animal animal = new Cat();

        // 調(diào)用了貓咪的吃方法
        animal.eat();

        // 向下轉(zhuǎn)型
        Dog dog = (Dog) animal;

        dog.walk(); // 調(diào)用的是 Dog 的 walk 可以通過,但是會運(yùn)行報錯
    }
}

得到結(jié)果:

小喵咪都喜歡吃魚罐頭!
Exception in thread "main" java.lang.ClassCastException: com.nz.pojo.Cat cannot be cast to com.nz.pojo.Dog
at com.nz.Demo4.main(Demo4.java:20)

我們可以看到,雖然我們的代碼通過編譯,但是終究在運(yùn)行時,還是出錯了,拋出了 ClassCastException 類型轉(zhuǎn)換的異常。

其實(shí)我們可以知道,我們在上面的時候,創(chuàng)建了Cat類型對象,而在向下轉(zhuǎn)型時,將其強(qiáng)行轉(zhuǎn)換為了Dog類型,所以程序在運(yùn)行時,就會拋出類型轉(zhuǎn)換的異常!

那我們?nèi)绾慰梢员苊膺@種異常發(fā)生呢?且看下一節(jié)分析!

6. instanceof關(guān)鍵字

Java為我們提供一個關(guān)鍵字instanceof ,它可以幫助我們避免了ClassCastException 類型轉(zhuǎn)換異常的發(fā)生。

那如何做呢?

格式:

變量名 instanceof 數(shù)據(jù)類型

解釋:

  • 如果變量屬于該數(shù)據(jù)類型或者其子類類型,返回true。
  • 如果變量不屬于該數(shù)據(jù)類型或者其子類類型,返回false。

代碼實(shí)現(xiàn):

package com.nz;

import com.nz.pojo.Animal;
import com.nz.pojo.Cat;
import com.nz.pojo.Dog;

/**
 * 使用instanceof解決類型轉(zhuǎn)換異常!
 */
public class Demo5 {
    public static void main(String[] args) {

        // 向上轉(zhuǎn)型的過程
        Animal animal = new Cat();

        // 調(diào)用了貓咪的吃方法
        animal.eat();

        // 向下轉(zhuǎn)型
        if (animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.playBall();        // 調(diào)用的是 Cat 的 playBall
        } else if (animal instanceof Dog){
            Dog dog = (Dog) animal;
            dog.walk();       // 調(diào)用的是 Dog 的 walk
        }
    }
}

結(jié)果:

小喵咪都喜歡吃魚罐頭!
小喵咪都喜歡小球!

可以發(fā)現(xiàn),它可以幫助我們在做類型轉(zhuǎn)換前,判斷該類型是否屬于該類型或者子類類型,如果是,我們就可以強(qiáng)轉(zhuǎn)啦!

總結(jié)

相信各位看官都對Java中的特性之一多態(tài)的知識和使用有了一定了解,等待下一次更多Java基礎(chǔ)的學(xué)習(xí)吧!

讓我們也一起加油吧!本人不才,如有什么缺漏、錯誤的地方,也歡迎各位人才大佬評論中批評指正!

學(xué)到這里,今天的世界打烊了,晚安!雖然這篇文章完結(jié)了,但是我還在,永不完結(jié)。我會努力保持寫文章。來日方長,何懼車遙馬慢!

感謝各位看到這里!愿你韶華不負(fù),青春無悔!

到此這篇關(guān)于Java多態(tài)的全面系統(tǒng)解析的文章就介紹到這了,更多相關(guān)Java 多態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java如何輸出windows中的全部漢字

    Java如何輸出windows中的全部漢字

    這篇文章主要介紹了Java如何輸出windows中的全部漢字問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • ElasticSearch添加索引代碼實(shí)例解析

    ElasticSearch添加索引代碼實(shí)例解析

    這篇文章主要介紹了ElasticSearch添加索引代碼實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Servlet Filter過濾器執(zhí)行順序

    Servlet Filter過濾器執(zhí)行順序

    這篇文章主要介紹了Servlet Filter過濾器執(zhí)行順序的相關(guān)資料,幫助大家更好的理解為什么要用過濾器,感興趣的朋友可以了解下
    2020-12-12
  • Java @Transactional與synchronized使用的問題

    Java @Transactional與synchronized使用的問題

    這篇文章主要介紹了Java @Transactional與synchronized使用的問題,了解內(nèi)部原理是為了幫助我們做擴(kuò)展,同時也是驗(yàn)證了一個人的學(xué)習(xí)能力,如果你想讓自己的職業(yè)道路更上一層樓,這些底層的東西你是必須要會的
    2023-01-01
  • Java使用httpRequest+Jsoup爬取紅藍(lán)球號碼

    Java使用httpRequest+Jsoup爬取紅藍(lán)球號碼

    本文將結(jié)合實(shí)例代碼,介紹Java使用httpRequest+Jsoup爬取紅藍(lán)球號碼,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • IDEA 2020.1打開時閃退的問題及解決方法(完美解決方法)

    IDEA 2020.1打開時閃退的問題及解決方法(完美解決方法)

    這篇文章主要介紹了IDEA 2020.1打開時閃退問題及解決方法,本文給大家分享我的處理方案,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • mybatisplus駝峰命名映射的問題解決

    mybatisplus駝峰命名映射的問題解決

    本文主要介紹了mybatisplus駝峰命名映射的問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Mybatis 插入和刪除批處理操作

    Mybatis 插入和刪除批處理操作

    在操作數(shù)據(jù)庫時,經(jīng)常會碰到批量插入、批量刪除的情況,直接執(zhí)行SQL語句還好做一點(diǎn),當(dāng)使用Mybatis進(jìn)行批量插入、批量刪除時會有一些問題。下面對使用Mybatis批量插入,批量刪除進(jìn)行介紹
    2016-12-12
  • Gradle:修改默認(rèn)的Build配置文件名方式

    Gradle:修改默認(rèn)的Build配置文件名方式

    這篇文章主要介紹了Gradle:修改默認(rèn)的Build配置文件名方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • SpringBoot 多Profile使用與切換方式

    SpringBoot 多Profile使用與切換方式

    這篇文章主要介紹了SpringBoot 多Profile使用與切換方式,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04

最新評論

榆树市| 甘孜| 缙云县| 尼玛县| 平安县| 汉川市| 蓬安县| 汶川县| 京山县| 永嘉县| 荥阳市| 武川县| 永宁县| 台江县| 常宁市| 葫芦岛市| 镶黄旗| 碌曲县| 迭部县| 衡山县| 梨树县| 吉林省| 兴义市| 铜陵市| 天峻县| 南城县| 微山县| 滦南县| 辉县市| 拜城县| 长兴县| 富顺县| 轮台县| 淮安市| 凌云县| 安西县| 辽阳县| 修武县| 稻城县| 土默特左旗| 蕉岭县|