2013-07-12 58 views
0

假設我們有:當「Fish f = new BlueFish();」時會發生什麼?

1 public class DynamicDispatch { 
    2  public static void main(String[] args) { 
    3   Fish f = new BlueFish(); 
    4   f.speak(); 
    5  } 
    6 } 
    7 
    8 abstract class Fish { 
    9  abstract String speak(); 
10 } 
11 
12 class BlueFish extends Fish { 
13  String speak() { 
14   return "I am a blue fish"; 
15  } 
16 } 
17 
18 class CatFish extends Fish { 
19  String speak() { 
20   return "I am a cat fish"; 
21  } 
22 } 

問題

  1. 從組件,青魚對象的創建。但爲什麼javac沒有意識到應該調用BlueFish.speak()

  2. 在運行期間,JVM如何處理invokespecial #4,以便調用正確的目標?

僅供參考,javap -c輸出爲:

Compiled from "DynamicDispatch.java" 
public class DynamicDispatch extends java.lang.Object{ 
public DynamicDispatch(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: new #2; //class BlueFish 
    3: dup 
    4: invokespecial #3; //Method BlueFish."<init>":()V 
    7: astore_1 
    8: aload_1 
    9: invokevirtual #4; //Method Fish.speak:()Ljava/lang/String; 
    12: pop 
    13: return 

} 
+6

您可以編譯它並查看生成的字節碼... –

+1

對象實例具有在運行時查找的虛擬方法表。該表是在實例化對象時構建的,因此特定於對象的類型。 Javac不需要知道對象類型是什麼就是從表中選擇方法編號4。 – BevynQ

+0

@BevynQ你能指出一些有關Java的虛擬方法表的參考嗎?謝謝! – JackWM

回答

0

答:

  1. 的javac不會嘗試去實現它,原因是其會很容易使局勢在那裏,java不會輕易發現,甚至根本無法發現。例如,您可能會發現是否使用CatFishBlueFish來使用用戶輸入。

  2. 對此,請參閱BevynQ的評論。我很驚訝他沒有把它作爲答案。

相關問題