Java 編譯時多態和運行時多態


        根據何時確定執行多態方法中的哪一個,多態分為兩種情況:編譯時多態和運行時多態。如果在編譯時能夠確定執行多態方法

中的哪一個,稱為編譯時多態,否則稱為運行時多態。


一、編譯時多態

       方法重載都是編譯時多態。根據實際參數的數據類型、個數和次序,Java在編譯時能夠確定執行重載方法中的哪一個。

        方法覆蓋表現出兩種多態性,當對象引用本類實例時,為編譯時多態,否則為運行時多態。例如,以下聲明p、m引用本類實例,調用toString()方法是編譯時多態。


public class Test {

public static void main(String[] args) {
Person p = new Person(); //對象引用本類實例
Man m = new Man(); //編譯時多態,執行Person類的toString()
System.out.println(p.toString());
System.out.println(m.toString()); //編譯時多態,執行Man類的toString()
}
}

class Person{
public String toString() {
String name = "Person";
return name;
}
}

class Man extends Person{
public String toString(){
String name = "Man";
return name;
}
}


二、運行時多態

1.當以下父類對象p引用子類實例時,p.toString)執行誰的setName()方法?

Person p = new Man();   
p.toString();

       Java支持運行時多態,意為p.toString()實際執行p所引用實例的toString(),究竟執行Person類還是Man類的方法,運行時再確定。如果Man類聲明了toString()方法,則執行之;否則執行Person類的toString()方法。


        程序運行時,Java從實例所屬的類開始尋找匹配的方法執行,如果當前類中沒有匹配的方法,則沿着繼承關系逐層向上,依次在父類或各祖先類中尋找匹配方法,直到Object類。尋找p.toString()匹配執行方法的過程如下圖所示。


        因此,父類對象只能執行那些在父類中聲明、被子類覆蓋了的子類方法,如toString(),不能執行子類增加的成員方法。


2.將上述例子中toString方法改為getName,因為在Object類中有toString類,無法測試Person與Man中所匹配的執行方法。

public class Test {   //例子2
public static void main(String[] args) {
Person p = new Man();
System.out.println(((Man) p).getName()); //返回結果為Man
}
}

class Person{}

class Man extends Person{
public String getName(){
String name = "Man";
return name;
}
}

此例中Person類型要引用Man類的實例,因Person中未定義setName()方法,故需要把Person類顯式地轉換為Man類,然后調用Man中的getName方法。


3.將例子1中Person和Man的方法名改為靜態的getName()方法,會返回什么結果呢?

public class Test {   //例子3

public static void main(String[] args) {
Person p = new Man();
System.out.println(p.type); //返回結果為P
System.out.println(p.getName()); //返回結果為Person

}

}

class Person{

String type = "P";
public static String getName() {
String name = "Person";
return name;
}
}

class Man extends Person{

String type = "M";
public static String getName(){
String name = "Man";
return name;
}
}

         栗子中子類Man隱藏父類Person的屬性,而 Person p = new Man() 表示“先聲明一個Person類的對象p,然后用Man類對 p進行實例化”,即引用類型為Person類,實際代表的是Man類。因此,訪問的是Person的屬性及靜態方法,詳細解釋如下。


        所謂靜態,就是在運行時,虛擬機已經認定此方法屬於哪個類。“重寫”只能適用於實例方法,不能用於靜態方法。對於靜態方法,只能隱藏,重載,繼承。

       子類對於父類靜態方法的隱藏(hide),子類的靜態方法完全體現不了多態,就像子類屬性隱藏父類屬性一樣,在利用引用訪問對象的屬性或靜態方法時,是引用類型決定了實際上訪問的是哪個屬性,而非當前引用實際代表的是哪個類。因此,子類靜態方法不能覆蓋父類的靜態方法。 

        父類中屬性只能被隱藏,而不能被覆蓋;而對於方法來說,方法隱藏只有一種形式,就是父類和子類存在相同的靜態方法。



參考文獻:

Java程序設計實用教程


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: