Java引用變量有兩個類型:編譯時類型和運行時類型。編譯時類型由聲明該變量時使用的類型決定,運行時類型由實際賦給該變量的對象決定。
若編譯時類型和運行時類型不一致,就出現多態
正常的方法調用(本態調用)
Person e = new Person(); e.say(); Student e = new Student(); e.say;
虛擬方法調用(多態情況下)
Person e = new Student(); e.say(); // 調用Student類的say()方法
編譯時類型和運行時類型
編譯時e為Person類型,而方法的調用是在運行時確定的,所以調用的是Student類的say()方法。——動態綁定
在虛擬方法調用情況下,方法看重寫后的,但屬性沒有重寫一說,e.name為Person中的name。
引用類型之間的類型轉換(對象的多態)
前提:父子關系
一、向上轉型
本質:父類的引用指向了子類的對象
語法:
父類類型 引用名 = new 子類類型();
特點:
編譯看左邊,運行看右邊
可以調用父類類型中的所有成員,不能調用子類類型中特有成員;最終運行效果看子類的具體實現!
二、向下轉型
語法:
子類類型 引用名 = (子類類型)父類引用;
特點:
① 只能強轉父類的引用,不能強轉父類的對象
② 要求父類的引用必須指向的是當前目標類型的對象(已經指向子類類型的)
③ 可以調用子類類型中所有的成員
示例:
public class TestPoly { public static void main(String[] args) { //子類——>父類 // 向上轉型(自動類型轉換):小——>大 Animal a =new Cat(); //可以調用哪些成員 a.eat(); a.run(); a.age=10; a.name=""; a.method(); // a.climb(); // 向下轉型(強制類型轉換) Cat c = (Cat) a; // Cat c2 = (Cat)(new Animal()); // 報錯,必須是父類的引用 // Animal b = new Pig(); // Cat c3 = (Cat)b; // 可能不報錯,但實際應用內部不是Pig
//可以調用哪些成員? c.run(); c.eat(); c.climb(); c.method(); c.name=""; c.age=1; c.color=""; } } class Animal{ String name; int age; public void eat(){ System.out.println("動物的吃"); } public void run(){ System.out.println("動物的跑"); } public void method(){ System.out.println("method"); } } class Pig extends Animal{ } class Cat extends Animal{ String color; public void run(){ System.out.println("貓飛快的跑"); } public void climb(){ System.out.println("貓爬樹"); } }
instanceof 判斷對象所屬類
x instanceof A:檢驗x是否為類A的對象,返回值為boolean型。
要求x所屬的類與類A必須是子類和父類的關系,否則編譯錯誤。
如果x屬於類A的子類B,x instanceof A值也為true。
public class Person extends Object {…} public class Student extends Person {…} public class Graduate extends Person {…} ------------------------------------------------------------------- public void method1(Person e) { if (e instanceof Person) // 處理Person類及其子類對象 if (e instanceof Student) //處理Student類及其子類對象 if (e instanceof Graduate) //處理Graduate類及其子類對象 }