Java三大特性之多態(tài)詳解
概述
引入
多態(tài)是繼封裝、繼承之后,面向?qū)ο蟮牡谌筇匦浴?生活中,比如跑的動(dòng)作,小貓、小狗和大象,跑起來(lái)是不一樣的。再比如飛的動(dòng)作,昆蟲(chóng)、鳥(niǎo)類(lèi)和飛機(jī),飛起來(lái)也是不一樣的??梢?jiàn),同一行為,通過(guò)不同的事物,可以體現(xiàn)出來(lái)的不同的形態(tài)。多態(tài),描述的就是這樣的狀態(tài)。
定義
多態(tài): 是指同一行為,具有多個(gè)不同表現(xiàn)形式。
多態(tài)的體現(xiàn)
多態(tài)體現(xiàn)的格式:
父類(lèi)類(lèi)型 變量名 = new 子類(lèi)對(duì)象; 變量名.方法名();
父類(lèi)類(lèi)型:指子類(lèi)對(duì)象繼承的父類(lèi)類(lèi)型,或者實(shí)現(xiàn)的父接口類(lèi)型。 代碼如下:
Fu f = new Zi(); f.method();
當(dāng)使用多態(tài)方式調(diào)用方法時(shí),首先檢查父類(lèi)中是否有該方法,如果沒(méi)有,則編譯錯(cuò)誤;如果有,執(zhí)行的是子類(lèi)重寫(xiě)后方法。 代碼如下: 定義父類(lèi):
public abstract class Animal { public abstract void eat(); }
定義子類(lèi):
class Cat extends Animal { public void eat() { System.out.println("吃魚(yú)??"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨頭??"); } }
定義測(cè)試類(lèi):
public class Test { public static void main(String[] args) { // 多態(tài)形式,創(chuàng)建對(duì)象 Animal a1 = new Cat(); // 調(diào)用的是 Cat 的 eat a1.eat(); // 多態(tài)形式,創(chuàng)建對(duì)象 Animal a2 = new Dog(); // 調(diào)用的是 Dog 的 eat a2.eat(); } }
多態(tài)的好處
實(shí)際開(kāi)發(fā)的過(guò)程中,父類(lèi)類(lèi)型作為方法形式參數(shù),傳遞子類(lèi)對(duì)象給方法,進(jìn)行方法的調(diào)用,更能體現(xiàn)出多態(tài)的擴(kuò)展性與便利。代碼如下: 定義父類(lèi):
public abstract class Animal { public abstract void eat(); }
定義子類(lèi):
class Cat extends Animal { public void eat() { System.out.println("吃魚(yú)??"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨頭??"); } }
定義測(cè)試類(lèi):
public class Test { public static void main(String[] args) { // 多態(tài)形式,創(chuàng)建對(duì)象 Cat c = new Cat(); Dog d = new Dog(); // 調(diào)用showCatEat showCatEat(c); // 調(diào)用showDogEat showDogEat(d); /** 以上兩個(gè)方法, 均可以被showAnimalEat(Animal a)方法所替代 而執(zhí)行效果一致 */ showAnimalEat(c); showAnimalEat(d); } public static void showCatEat (Cat c){ c.eat(); } public static void showDogEat (Dog d){ d.eat(); } public static void showAnimalEat (Animal a){ a.eat(); } }
由于多態(tài)特性的支持,showAnimalEat方法的Animal類(lèi)型,是Cat和Dog的父類(lèi)類(lèi)型,父類(lèi)類(lèi)型接收子類(lèi)對(duì)象,當(dāng)然可以把Cat對(duì)象和Dog對(duì)象,傳遞給方法。 當(dāng)eat方法執(zhí)行時(shí),多態(tài)規(guī)定,執(zhí)行的是子類(lèi)重寫(xiě)的方法,那么效果自然與showCatEat、showDogEat方法一致, 所以showAnimalEat完全可以替代以上兩方法。 不僅僅是替代,在擴(kuò)展性方面,無(wú)論之后再多的子類(lèi)出現(xiàn),我們都不需要編寫(xiě)showXxxEat方法了,直接使用 showAnimalEat都可以完成。 所以,多態(tài)的好處,體現(xiàn)在,可以使程序編寫(xiě)的更簡(jiǎn)單,并有良好的擴(kuò)展。
引用類(lèi)型轉(zhuǎn)換
多態(tài)的轉(zhuǎn)型分為向上轉(zhuǎn)型與向下轉(zhuǎn)型兩種:
向上轉(zhuǎn)型
向上轉(zhuǎn)型:多態(tài)本身是子類(lèi)類(lèi)型向父類(lèi)類(lèi)型向上轉(zhuǎn)換的過(guò)程,這個(gè)過(guò)程是默認(rèn)的。 當(dāng)父類(lèi)引用指向一個(gè)子類(lèi)對(duì)象時(shí),便是向上轉(zhuǎn)型。 使用格式:
父類(lèi)類(lèi)型 變量名 = new 子類(lèi)類(lèi)型(); 如:Animal a = new Cat();
向下轉(zhuǎn)型
向下轉(zhuǎn)型:父類(lèi)類(lèi)型向子類(lèi)類(lèi)型向下轉(zhuǎn)換的過(guò)程,這個(gè)過(guò)程是強(qiáng)制的。 一個(gè)已經(jīng)向上轉(zhuǎn)型的子類(lèi)對(duì)象,將父類(lèi)引用轉(zhuǎn)為子類(lèi)引用,可以使用強(qiáng)制類(lèi)型轉(zhuǎn)換的格式,便是向下轉(zhuǎn)型。 使用格式:
子類(lèi)類(lèi)型 變量名 = (子類(lèi)類(lèi)型) 父類(lèi)變量名; 如:Cat c =(Cat) a;
為什么要轉(zhuǎn)型
當(dāng)使用多態(tài)方式調(diào)用方法時(shí),首先檢查父類(lèi)中是否有該方法,如果沒(méi)有,則編譯錯(cuò)誤。也就是說(shuō),不能調(diào)用子類(lèi)擁有,而父類(lèi)沒(méi)有的方法。編譯都錯(cuò)誤,更別說(shuō)運(yùn)行了。這也是多態(tài)給我們帶來(lái)的一點(diǎn)"小麻煩"。所以,想要調(diào)用子類(lèi)特有的方法,必須做向下轉(zhuǎn)型。 轉(zhuǎn)型演示,代碼如下: 定義類(lèi):
abstract class Animal { abstract void eat(); } class Cat extends Animal { public void eat() { System.out.println("吃魚(yú)??"); } public void catchMouse() { System.out.println("抓老鼠??"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨頭??"); } public void watchHouse() { System.out.println("看家??"); } }
定義測(cè)試類(lèi):
public static void main(String[] args) { // 向上轉(zhuǎn)型 Animal a = new Cat(); a.eat(); // 調(diào)用的是 Cat 的 eat // 向下轉(zhuǎn)型 Cat c = (Cat)a; c.catchMouse(); // 調(diào)用的是 Cat 的 catchMouse }
轉(zhuǎn)型的異常
轉(zhuǎn)型的過(guò)程中,一不小心就會(huì)遇到這樣的問(wèn)題,請(qǐng)看如下代碼:
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)行報(bào)錯(cuò)】 } }
這段代碼可以通過(guò)編譯,但是運(yùn)行時(shí),卻報(bào)出了 ClassCastException ,類(lèi)型轉(zhuǎn)換異常!這是因?yàn)椋髅鲃?chuàng)建了Cat類(lèi)型對(duì)象,運(yùn)行時(shí),當(dāng)然不能轉(zhuǎn)換成Dog對(duì)象的。這兩個(gè)類(lèi)型并沒(méi)有任何繼承關(guān)系,不符合類(lèi)型轉(zhuǎn)換的定義。為了避免ClassCastException的發(fā)生,Java提供了 instanceof 關(guān)鍵字,給引用變量做類(lèi)型的校驗(yàn),格式如下:
變量名 instanceof 數(shù)據(jù)類(lèi)型 如果變量屬于該數(shù)據(jù)類(lèi)型,返回true。 如果變量不屬于該數(shù)據(jù)類(lèi)型,返回false。
所以,轉(zhuǎn)換前,我們最好先做一個(gè)判斷,代碼如下:
public class Test { public static void main(String[] args) { // 向上轉(zhuǎn)型 Animal a = new Cat(); a.eat(); // 調(diào)用的是 Cat 的 eat // 向下轉(zhuǎn)型 if (a instanceof Cat){ Cat c = (Cat)a; c.catchMouse(); // 調(diào)用的是 Cat 的 catchMouse } else if (a instanceof Dog){ Dog d = (Dog)a; d.watchHouse(); // 調(diào)用的是 Dog 的 watchHouse } } }
以上就是Java三大特性之多態(tài)詳解的詳細(xì)內(nèi)容,更多關(guān)于Java多態(tài)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java根據(jù)控制臺(tái)實(shí)現(xiàn)定位異常
這篇文章主要介紹了Java根據(jù)控制臺(tái)定位異常,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05Java 多線(xiàn)程有序執(zhí)行的幾種方法總結(jié)
這篇文章主要介紹了Java 多線(xiàn)程有序執(zhí)行的幾種方法總結(jié)的相關(guān)資料,需要的朋友可以參考下2017-03-03Java中final,finally,finalize三個(gè)關(guān)鍵字的區(qū)別_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章給大家收集整理了有關(guān)java中final,finally,finalize三個(gè)關(guān)鍵字的區(qū)別介紹,非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下吧2017-04-04IDEA在Maven項(xiàng)目中使用本地jar包的方法
我們?cè)谀玫脚f項(xiàng)目的時(shí)候,經(jīng)常會(huì)遇到一種情況,就是這個(gè)項(xiàng)目的maven中依賴(lài)了一個(gè)本地的jar包,這種情況就需要引入這個(gè)jar包,所以本文給大家介紹了IDEA在Maven項(xiàng)目中使用本地jar包的方法,需要的朋友可以參考下2024-04-04