2014-07-20 31 views
3

爲什麼Java不支持靜態方法的動態多態? 如果答案是「靜態方法不應該在實例上調用,因此方法調用不需要在運行時解析」,那麼進一步的問題是「爲什麼Java允許我調用實例上的靜態方法?」。爲什麼它不會阻止用戶直接通過給一些編譯時錯誤來調用實例上的方法?不支持Java中靜態方法的動態多態的原因

其他問題如果Java支持靜態方法的Runtime Polymorphism,會出現什麼問題?

+0

它根本沒有意義。由於該類是在編譯時確定的,因此不存在多態性的可能性。並且在一個實例上調用一個靜態方法有點(笨,IMO)編譯器。你真正在做的是在編譯時確定的引用變量的聲明類上調用靜態方法。 –

+1

我同意你的意見,但我的查詢是爲什麼不阻止你不想讓用戶使用的功能。 – t22

+1

Smalltalk確實支持這個,所以完全可以實現。我認爲這只是爲java所做的設計決策之一,說實話我從來沒有錯過它。 – Seb

回答

6

爲什麼Java允許我在實例上調用靜態方法?

你的假設是錯誤的。它永遠不會調用該類的實例。它總是呼籲上課。

試試下面的示例代碼,你將永遠不會得到NullPointerException

class ABC { 
    public static void hello() { 
     System.out.println("Hello"); 
    } 
} 

ABC abc = null; 
abc.hello(); 

什麼會出現了問題,如果Java的會支持運行時多態性的靜態方法?

Polymorphism當你在override子類中的方法進入圖片。因爲靜態方法屬於類,因此沒有重寫靜態方法的意義。因此,多態性總是適用於僅屬於該類實例的方法。

+0

我假設,你有實例(實例化類),以調用靜態方法。 – t22

+1

我沒有任何類的實際對象。這是一個'null'引用。 – Braj

+1

儘管這是完全正確的;可以構建一個適用於靜態方法的自我一致的繼承模型(並且在某些情況下可能很有用 - 例如,每個擴展'Tile'的類都有一個靜態的'initialiseGraphicsForClass'方法,並將一個類傳遞給方法)。所以問題依然存在。爲什麼不? –

-1

我很高興我可以通過一個類的實例調用靜態方法。它讓我無需限定就可以從實例中調用方法。而且,如果我試圖通過一個實例(合法但非理性地稱其爲),我的IDE會提醒我。

public static void foo() { 
    //yadda yadda 
} 

public void bar() { 
    foo(); // this is legal 
    MyClass.foo() // this is also legal, but would be necessary if I couldn't call it through the instance 
} 

// in some other class: 
new MyClass().foo() // this is legal but silly and my IDE warns me about it 
+1

但是,如果超類聲明瞭一個名爲foo的實例方法,會發生什麼情況?應該調用哪種方法:實例方法還是靜態方法?我相信實例方法優先於靜態方法被調用。意思是另一個人可能會改變超類,而沒有意識到他們正在影響這個子類。 – Dunes

1

靜態方法根據變量的類型而不是實例的類來解析。這允許進行一些優化,因爲要在編譯時知道確切的方法是總是。允許多態靜態方法可以防止這種情況。

允許在實例上調用靜態方法的結果如下。

class A { 
    static void func() {} 
} 

class B extends A { 
    static void func() {} 
} 

B b = new B(); 
A a = b; 

b.func(); // calls B.func() 
a.func(); // same instance, but calls A.func() 

非常令人困惑,並且反直觀。基於如何實現靜態方法,允許在實例上調用靜態方法是一個主要的設計缺陷,應始終避免。

根據定義,靜態方法不需要調用實例。通過允許多態調用,您需要一個實例,並且如果您需要實例來確定要調用哪個方法,那麼爲什麼該方法是靜態的?

+2

我真的不贊成爲靜態方法支持動態多態,但如果java支持實例的靜態方法調用調用,那麼它應該完全支持它(例如實例方法)或阻止用戶完全調用實例的靜態方法。 – t22