深度分析:理解Java中的多態機制,一篇直接幫你掌握!

Java中的多態

1 多態是什麼

多態(Polymorphism)按字面的意思就是「多種狀態」。在面嚮對象語言中,接口的多種不一樣的實現方式即爲多態。用白話來講,就是多個對象調用同一個方法,獲得不一樣的結果。java

2 多態的語法格式

父類類名 引用名稱 = new 子類類名();ide

當是多態時,該引用名稱只能訪問父類中的屬性和方法,可是訪問的時候,會優先訪問子類重寫之後的方法。測試

3 知足多態的條件

子類必須繼承父類
子類必須重寫父類的方法
父類引用指向子類對象,即:父類類名 引用名稱 = new 子類類名();
4 使用多態好處
使用多態可使代碼之間的耦合度下降code

減小冗餘代碼的同時,也使得項目的擴展能力更強對象

注:耦合度指的是代碼(程序)之間的關聯程度繼承

5 多態中的類型轉換

Java多態中,有兩種類型轉換:向上轉型和向下轉型接口

向上轉型
向上轉型,也叫作自動類型轉換,子類型賦值給父類型(父類型的引用指向子類型),構成多態
父類類型 引用名稱 = new 子類類名();編譯器

當使用多態方式調用方法時,該引用名稱只能訪問父類中的屬性和方法。編譯器首先檢查父類中是否有該方法,若是沒有,則編譯錯誤。若是有,再去調用子類的同名(重寫)方法。博客

向下轉型
向下轉型,也叫作強制類型轉換,父類型賦值給子類型io

當使用多態時,而且訪問子類獨有的屬性或方法時,則必須進行向下轉型

當進行向下轉型時,建議先使用 instance of 關鍵字進行判斷,判斷合法時,則在轉爲對應的類型,不然可能會出現類型轉換異常 java.lang.ClassCastException。

說明:instance of 關鍵字用於判斷一個對象,是否屬於某個指定的類或其子類的實例。

6 多態的實現方式

普通子類重寫父類方法

接口
生活中的接口最具表明性的就是插座,例如一個三接頭的插頭都能接在三孔插座中,由於這個是每一個國家都有各自規定的接口規則,有可能到國外就不行,那是由於國外本身定義的接口類型。

USB接口也很典型,有了這個,使得接口統一,生活更加方便

抽象類和抽象方法

7 多態簡單使用案例

場景:假若有個飼養員,須要給不一樣的寵物餵食,下面給出使用多態和不使用多態的實現方式。

不使用多態的實現:

首先定義一個抽象類Animal、一個飼養員類AnimalKeeper、一個寵物類Dog和一個寵物類Cat。

public abstract class Animal {

    public void eat() {
        System.out.println("動物吃東西!");
    }
}
/**
 * 飼養員
 */
public class AnimalKeeper {

    /**
     * 給寵物貓餵食
     *
     * @param cat
     */
    public void feed(Cat cat) {
        cat.eat();
    }

    /**
     * 給寵物狗餵食
     *
     * @param dog
     */
    public void feed(Dog dog) {
        dog.eat();
    }

}
public class Dog extends Animal {

    @Override
    public void eat() {
        System.out.println("狗啃骨頭!");
    }
}
public class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("貓吃魚!");
    }
}

測試類:

public class PolymorphicTest {

    public static void main(String[] args) {
        //建立飼養員對象
        AnimalKeeper animalKeeper = new AnimalKeeper();

        //建立寵物對象
        Cat cat = new Cat();
        animalKeeper.feed(cat);//貓吃魚!

        Dog dog = new Dog();
        animalKeeper.feed(dog);//狗啃骨頭!
    }
}

以上實現看起來沒有什麼問題,也容易理解,在目前狀況下,飼養員能夠知足餵養寵物的需求。可是,過了一週,飼養員又餵養了一隻鳥,這時候不得不修改AnimalKeeper類,使其能夠飼養寵物鳥,不只違反了Java中的開閉原則,並且以上代碼的實現,擴展性極差。

使用多態的實現:

只須要對以上代碼中,飼養員類AnimalKeeper進行替換,新增一個飼養員類AnimalKeeperPolymorphic類。

/**
 * 飼養員
 */
public class AnimalKeeperPolymorphic {

    /**
     * 飼養員給寵物餵食
     *
     * @param animal
     */
    public void feed(Animal animal) {
        animal.eat();
    }

}

測試用例:

public static void change() {
   //建立飼養員對象
    AnimalKeeperPolymorphic animalKeeper = new AnimalKeeperPolymorphic();

    //建立寵物對象
    Cat cat = new Cat();
    animalKeeper.feed(cat);//貓吃魚!

    Dog dog = new Dog();
    animalKeeper.feed(dog);//狗啃骨頭!
}

這種實現有什麼好處呢,當新需求來了,須要擴展時,不須要修改飼養員的代碼。好比說剛纔那個需求,新增長一個寵物鳥,只須要新建一個寵物鳥類,實現Animal接口,不只遵循了OCP原則,也能夠實現飼養寵物鳥的功能。

8 多態分析

以上文中示例代碼進行分析,看看多態是如何使用的。

AnimalKeeperPolymorphic中的feed()方法,使用了多態。

當飼養員餵養寵物狗時,其實執行的是:

Animal animal = new Dog();

當飼養員餵養寵物貓時,其實執行的是:

Animal animal = new Cat();

這種屬於向上轉型,裏面有繼承(cat繼承Animal)關係,重寫了父類eat()方法,子類型賦值給父類型(父類型的引用指向子類型),構成了多態。

Animal animal = new Cat(); 程序在編譯階段,animal引用類型被編譯器看作Animal類型,因此程序在編譯階段,animal引用綁定的是Aninmal類中的eat()方法,這個過程叫作Java多態的靜態綁定。

程序在運行的時候,堆中的對象其實是Cat類型,而Cat對象已經覆蓋(重寫)了父類Animal的eat()方法,因此程序在運行階段,對象綁定的方法是Cat中的eat()方法,這個過程叫作Java多態的動態綁定。

寫博客是爲了記住本身容易忘記的東西,另外也是對本身工做的總結,但願盡本身的努力,作到更好,你們一塊兒努力進步! 若是有什麼問題,歡迎你們一塊兒探討,代碼若有問題,歡迎各位大神指正! 給本身的夢想添加一雙翅膀,讓它能夠在天空中自由自在的飛翔!
相關文章
相關標籤/搜索