面試常考基礎,向上轉型與向下轉型(穿插講解多態的編譯時多態和運行時多態)
前言
這個跟繼承一起考,如果了解好這個后,會幫助你加強對多態的概念。就不會當聽到多態,第一時間想到的時候就是重寫和重載,但是應該不只是想到這一些,還得想到并理解好編譯時多態和運行時多態。
正文
向上轉型
在說概念之前,我感覺應該先來個例子吧來看看吧
class Animal{
public void eat(){
System.out.println("動物吃");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃");
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Animal b = new Dog();
b.eat();
}
}
運行截圖:

a.eat(),運行結果是“動物吃”
b.eat(),運行結果是“狗吃”,由于b中,Dog類重寫了eat(),且在向上轉型中,子類如果有對應的函數,且不是子類所特有的,父類也有該函數,那么就選擇執行子類中的函數;如果子類沒有該函數,那么去看父類中的情況,如果有就執行父類中的函數。
這里就體現了向上轉型十分的靈活,但是他也有缺點,就是我前面也提到了的執行子類中的函數時,需不是子類所特有的。
而在這里我就穿個
如以下的例子
package com.atguigu.daijia.customer.service.impl;
class Animal{
public void eat(){
System.out.println("動物吃");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃");
}
public void bark(){
System.out.println("狗吠");
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Animal b = new Dog();
b.bark();
}
}
運行截圖:

這里也看出來了,其實向上轉型的含義就是創建一個子類對象,將其當成父類對象來使用。
錯誤的原因很簡單,就是b 的編譯時類型是 Animal,而 Animal 類里并沒有聲明 bark() 方法,所以編譯器直接報錯:找不到符號。這就是向上轉型的缺點就是無法調用子類所特有的方法,但是你們也看到了截圖里面b.bark();旁邊有ai提示我該怎么改,這個也就是后面的向上轉型了。
在這里我就是一起講一下運行時多態,我們說到的向上轉型是創建一個子類對象,將其當成父類對象來使用,也可以說成父類引用指向子類對象。(這里參考了https://blog.csdn.net/xylitolz/article/details/115800775)
父類只能執行那些在父類中聲明、被子類覆蓋了的子類方法,而不能執行子類新增加的成員方法。在編譯時期,首先會去查看父類里面有沒有這個方法,如果沒有的話向上繼續查找,直到找到Object類如果還沒有的話就報錯,如果有的話,到運行階段,再去看一下子類中有沒有覆蓋該方法,如果覆蓋了,則執行子類覆蓋的方法。如果沒有則執行父類中原本的方法。這個結合我上面的例子。
當子類和父類有相同屬性時,父類還是會執行自己所擁有的屬性,若父類中沒有的屬性子類中有,在編譯時期就會報錯
運行截圖:


對于static方法還是會執行父類中的方法,這是由于在運行時,虛擬機已經認定static方法屬于哪個類。“重寫”只能適用于實例方法,不能用于靜態方法。在利用引用訪問對象的屬性或靜態方法時,是引用類型決定了實際上訪問的是哪個屬性,而非當前引用實際代表的是哪個類。
既然說了運行時多態,就隨便把編譯時多態講了,其實從上面我們就發現了父子之間同名函數使用的一些邏輯了把,重寫對應運行時多態,那么其實重載對應的是編譯時多態
拿重載來說,在同一個類中,出現了多個同名的方法,而區分他們是由于形參列表不同,而根據參數的數據類型、個數和次序,Java在編譯時能夠確定執行重載方法中的哪一個。
向下轉型
在上面說,若想調用子類獨有的函數,應該進行向下轉型。將父類對象再還原為子類對象,就是對原本的子類向上轉型之后可以當成父類對象使用,然后再向下轉型為子類對象。
package com.atguigu.daijia.customer.service.impl;
class Animal{
public int speed=10;
public void eat(){
System.out.println("動物吃");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃");
}
public void bark(){
System.out.println("狗吠");
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Animal b = new Dog();
//b.bark();
((Dog)b).bark();
}
}
運行截圖:


浙公網安備 33010602011771號