網(wǎng)站建設(shè)福州產(chǎn)品網(wǎng)絡(luò)推廣的方法
文章目錄
- 1、多態(tài)的介紹
- 2、多態(tài)的格式
- 3、對(duì)象的強(qiáng)制類(lèi)型轉(zhuǎn)換
- 4、instanceof 運(yùn)算符
- 5、案例:筆記本USB接口
1、多態(tài)的介紹
多態(tài)(Polymorphism)按字面意思理解就是“多種形態(tài)”,即一個(gè)對(duì)象擁有多種形態(tài)。
即同一種方法可以根據(jù)發(fā)送對(duì)象的不同而采用多種不同的行為方式。
一個(gè)對(duì)象的實(shí)際類(lèi)型是確定的,但可以指向?qū)ο蟮囊玫念?lèi)型有很多。
多態(tài)存在的條件
- 有繼承(基類(lèi))或 實(shí)現(xiàn) (接口) 關(guān)系
- 子類(lèi)重寫(xiě)父類(lèi)的方法
- 父類(lèi)引用變量指向子類(lèi)對(duì)象
==注:==多態(tài)是針對(duì)實(shí)例方法的多態(tài),不是屬性的多態(tài),也不是類(lèi)方法的多態(tài)。
java 引用變量分為兩種類(lèi)型,一種是編譯時(shí)類(lèi)型,一種是運(yùn)行時(shí)類(lèi)型。
編譯時(shí)類(lèi)型由聲明該變量時(shí)使用的類(lèi)型決定;運(yùn)行時(shí)類(lèi)型由實(shí)際賦值給該變量的對(duì)象決定。
如果編譯時(shí)類(lèi)型和運(yùn)行時(shí)類(lèi)型不一致,就**可能(重寫(xiě)了方法的話)**出現(xiàn)所謂的多態(tài)。
class Person {public void eat() { }
}class Student extends Person {// 重寫(xiě)了基類(lèi)中的方法public void eat() {}// 子類(lèi)中特有的方法public void study() {}
}class Applicaton {public static void main(String[] args) {// 不存在多態(tài) 編譯時(shí)類(lèi)型和運(yùn)行時(shí)類(lèi)型一致Student s3 = new Student();// 不存在多態(tài) 編譯時(shí)類(lèi)型和運(yùn)行時(shí)類(lèi)型一致Person s2 = new Person();// 存在多態(tài) 編譯時(shí)類(lèi)型和運(yùn)行時(shí)類(lèi)型不一致,重寫(xiě)了基類(lèi)中的方法Person s1 = new Student();s1.eat();// 報(bào)錯(cuò) 原因下方會(huì)解釋// s1.study();}
}
當(dāng)把一個(gè)子類(lèi)對(duì)象直接賦值給父類(lèi)引用變量時(shí):
例如上面的 Person s1 = new Student();
這個(gè) s1 的引用變量的編譯類(lèi)型是 Person,而運(yùn)行時(shí)類(lèi)型是 Student,當(dāng)運(yùn)行時(shí)調(diào)用該引用變量的方法時(shí),其方法行為總是表現(xiàn)出子類(lèi)方法的行為特征,而不是父類(lèi)方法的行為特征,這就可能出現(xiàn):相同類(lèi)型的變量調(diào)用同一個(gè)方法時(shí)呈現(xiàn)出多種不同的行為特征,這就是多態(tài)。
這里的相同類(lèi)型就是指同一個(gè)引用變量(s1),調(diào)用同一個(gè)方法,但指向不同的子類(lèi)對(duì)象時(shí),表現(xiàn)出不同的行為特征。
注:
1、通過(guò)引用變量來(lái)直接訪問(wèn)其包含的實(shí)例變量時(shí),系統(tǒng)總是試圖訪問(wèn)它編譯時(shí)類(lèi)型定義的實(shí)例變量,而不是運(yùn)行時(shí)類(lèi)型所定義的實(shí)例變量。
2、引用變量在編譯階段只能調(diào)用其編譯時(shí)類(lèi)型所具有的方法,但運(yùn)行階段則可以調(diào)用它運(yùn)行時(shí)類(lèi)型所具有的的方法。
還是上面的例子:Person s1 = new Student();
s1 引用變量只能調(diào)用 Person 類(lèi)的方法,不能直接調(diào)用 Student 里獨(dú)有的方法。
作用
簡(jiǎn)單來(lái)說(shuō),就是建立一個(gè)父類(lèi)對(duì)象的引用變量,指向不同的子類(lèi)對(duì)象。
把不同的子類(lèi)對(duì)象都當(dāng)做父類(lèi)來(lái)看待,屏蔽不同子類(lèi)對(duì)象之間的差異,寫(xiě)出通用的代碼,以適應(yīng)需求的不斷變化。
而且無(wú)論右邊 new 的時(shí)候換成了哪個(gè)子類(lèi)對(duì)象,等號(hào)左邊的調(diào)用方法都不會(huì)變化。
2、多態(tài)的格式
- 代碼當(dāng)中體現(xiàn)多態(tài)性,其實(shí)就是一句話:父類(lèi)引用指向子類(lèi)對(duì)象。
- 格式:
基類(lèi)類(lèi)型 引用變量名稱(chēng) = new 子類(lèi)類(lèi)型(); // 通過(guò)繼承實(shí)現(xiàn)
or
接口類(lèi)型 引用變量名稱(chēng) = new 實(shí)現(xiàn)類(lèi)類(lèi)型(); // 通過(guò)接口實(shí)現(xiàn)
對(duì)象的自動(dòng)類(lèi)型
多態(tài)的寫(xiě)法其實(shí)就是對(duì)象的自動(dòng)類(lèi)型(類(lèi)型向上轉(zhuǎn)),只不過(guò)是編譯器自動(dòng)完成的。
注:
向上轉(zhuǎn)型一定是成功的,這也證實(shí)了子類(lèi)其實(shí)是一種特殊的父類(lèi)。
這種類(lèi)型轉(zhuǎn)換只是表明這個(gè)引用變量的編譯時(shí)類(lèi)型是基類(lèi),運(yùn)行時(shí)類(lèi)型是子類(lèi),執(zhí)行方法時(shí)表現(xiàn)的是子類(lèi)對(duì)象的行為方式。
如果想讓基類(lèi)引用變量調(diào)用子類(lèi)中特有的方法,就需要進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換。
3、對(duì)象的強(qiáng)制類(lèi)型轉(zhuǎn)換
強(qiáng)制類(lèi)型轉(zhuǎn)換需要借助于類(lèi)型轉(zhuǎn)換運(yùn)算符—— (類(lèi)型)
。
類(lèi)型轉(zhuǎn)換運(yùn)算符的用法:(類(lèi)型)變量名稱(chēng)
通過(guò)類(lèi)型轉(zhuǎn)換運(yùn)算符將一個(gè)父類(lèi)引用變量強(qiáng)轉(zhuǎn)成子類(lèi)引用變量時(shí),需要注意一下幾點(diǎn):
1、基本類(lèi)型之間的轉(zhuǎn)換只能在數(shù)值類(lèi)型之間進(jìn)行。
數(shù)值類(lèi)型:整型(byte、short、int、long)、字符型(char)、浮點(diǎn)型(float、double)。
數(shù)值類(lèi)型和布爾類(lèi)型之間不能進(jìn)行類(lèi)型轉(zhuǎn)換。
2、引用類(lèi)型之間的轉(zhuǎn)換只能在具有繼承 or 實(shí)現(xiàn)關(guān)系的兩個(gè)類(lèi)型之間進(jìn)行,如果把兩個(gè)不相關(guān)的類(lèi)型之間進(jìn)行轉(zhuǎn)換,則會(huì)報(bào)類(lèi)型轉(zhuǎn)換異常:ClassCastException
示例
Person s1 = new Student();
// Person 類(lèi)中沒(méi)有 study() 方法 進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換
((Student) s1).study();
考慮到進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換時(shí)可能出現(xiàn)的異常,因此進(jìn)行類(lèi)型轉(zhuǎn)換之前應(yīng)先通過(guò) instanceof 運(yùn)算符來(lái)判斷是否可以成功轉(zhuǎn)換,避免出現(xiàn)異常,以增強(qiáng)程序的健壯性。
4、instanceof 運(yùn)算符
使用:A instanceof B
作用:判斷其左邊對(duì)象(指運(yùn)行時(shí)對(duì)象)是否為其右邊類(lèi)的實(shí)例,返回 boolean 類(lèi)型的數(shù)據(jù)。
如果 A 和 B 不存繼承話,會(huì)出現(xiàn)編譯錯(cuò)誤。
示例 1:
class Animal {}class Cat extends Animal {}class Dog extends Animal {}class Applicaton {public static void main(String[] args) {Animal animal = new Dog();if (animal instanceof Dog) {System.out.println("汪汪~(yú)");} else if (animal instanceof Cat) {System.out.println("喵喵~");}}
}
實(shí)例 2:
// obj引用變量 編譯時(shí)類(lèi)型是 Object,運(yùn)行時(shí)類(lèi)型是String
// 因?yàn)镺bject是所有類(lèi)、接口的父類(lèi),所以以下才可通過(guò)
Object obj = "chatGPT";
// String 是 Object 類(lèi)的實(shí)例
System.out.println(obj instanceof Object);
// String 是 String 類(lèi)的實(shí)例
System.out.println(obj instanceof String);
// String 不是 Math 類(lèi)的實(shí)例
System.out.println(obj instanceof Math);
// String 是 Comparable 接口的實(shí)例。接口理解成一種特殊的類(lèi)
System.out.println(obj instanceof Comparable);// 注意:這里的 str 沒(méi)有用多態(tài)的寫(xiě)法
String str = "hello";// 編譯不通過(guò),str引用變量編譯時(shí)類(lèi)型是String和Math沒(méi)有繼承關(guān)系
// System.out.println(str instanceof Math);// String 對(duì)象是 Object 類(lèi)的實(shí)例
System.out.println(str instanceof Object);
5、案例:筆記本USB接口
重點(diǎn):接口的基本使用、對(duì)象的上下轉(zhuǎn)型以及使用接口作為方法的參數(shù)。
Computer 使用 USB接口,Mouse、KeyBoards 實(shí)現(xiàn) USB接口
USB 接口
// USB接口類(lèi)
public interface USB {void open();void close();
}
Computer 類(lèi)
// 電腦類(lèi)
public class Computer {public void powerOn(){System.out.println("電腦開(kāi)機(jī)");}public void powerOff(){System.out.println("電腦關(guān)機(jī)");}// 接口作為方法的參數(shù)public void useDevice(USB usb){usb.open();if (usb instanceof Mouse){ // 一定要先判斷Mouse mouse = (Mouse)usb; // 向下轉(zhuǎn)型mouse.click();} else if (usb instanceof KeyBoard) {KeyBoard keyboard = (KeyBoard)usb;keyboard.type();}usb.close();}
}
Mouse 類(lèi)
// 鼠標(biāo)類(lèi)
public class Mouse implements USB{@Overridepublic void open() {System.out.println("打開(kāi)鼠標(biāo)");}@Overridepublic void close() {System.out.println("關(guān)閉鼠標(biāo)");}public void click(){System.out.println("鼠標(biāo)點(diǎn)擊");}
}
KeyBoard 類(lèi)
// 鍵盤(pán)類(lèi)
public class KeyBoard implements USB{@Overridepublic void open() {System.out.println("打開(kāi)鍵盤(pán)");}@Overridepublic void close() {System.out.println("關(guān)閉鍵盤(pán)");}public void type(){System.out.println("鍵盤(pán)輸入");}
}
Demo02Main 測(cè)試類(lèi)
public class Demo02Main {public static void main(String[] args) {Computer computer = new Computer();computer.powerOn();USB usbMouse = new Mouse();computer.useDevice(usbMouse);// USB usbKeyBoard = new KeyBoard();KeyBoard keyBoard = new KeyBoard();computer.useDevice(keyBoard);computer.powerOff();}
}