2011-02-13 121 views
9

爲什麼下面的代碼打印「Main」?靜態方法的繼承

public class Main 
{ 
    public static void method() 
    { 
     System.out.println("Main"); 
    } 

    public static void main(String[] args) 
    { 
     Main m = new SubMain(); 
     m.method(); 
    } 
} 

class SubMain extends Main 
{ 
    public static void method() 
    { 
     System.out.println("SubMain"); 
    } 
} 

在運行時,m指向的Submain一個實例,所以應該在概念上打印「SubMain」。

+3

你甚至可以寫`Main m = null;`然後調用方法,表達式在點之前根本不用。 – 2011-02-13 23:19:58

回答

18

靜態方法在變量的編譯時類型上得到解決。 m類型爲Main,因此調用Main中的方法。

如果將其更改爲SubMain m ...,則將調用SubMain上的方法。

+13

除了這個答案,我建議你不要從實例對象中調用靜態方法,並從類名(例如:SubMain.method()而不是m.method())中調用它們。 – andrewjs 2011-02-13 22:48:20

2

Eclipse中給了我這種警告,當我嘗試做這樣的事情:

靜態方法XXX()從類型XXX應以靜態方式

訪問靜態方法不參與繼承。該變量的類型爲Main,因此編譯器將您的函數調用解析爲Main.method()

爲了增添趣味,請嘗試將m設置爲null

15

這是因爲靜態方法不是多態的。此外,靜態方法不應該由對象調用,而應該使用類,即Main.method()SubMain.method()。 當您致電m.method()時,java實際上調用Main.method(),因爲m的類型是Main。

如果您想享受多態,請不要使用靜態方法。

1

Java執行靜態方法的早期綁定,與動態綁定的實例方法不同。

因爲您的對象變量是Main類型的,所以調用在編譯時綁定到超類實現。

有一個很好的解釋here

0

靜態方法與它們的類名稱是靜態綁定的,因爲m是Main類的類型 然後在編譯後它看起來像下面的樣子 Main.method(); 類的編譯後 運行以下命令 的javap -c主要 ü可以看到主類 JVM的彙編代碼和u會看到以下 m.method //調用靜態 調用靜態,調用特殊告訴靜綁定 調用特殊的,調用接口告訴動態綁定