2011-02-10 21 views
26

我有一個快速和簡單明瞭的問題:多態性與方法重載

我有這個簡單的類:

public class A 
{ 
    public void m(Object o) 
    { 
     System.out.println("m with Object called"); 
    } 

    public void m(Number n) 
    { 
     System.out.println("m with Number called"); 
    } 
    public static void main(String[] args) 
    { 
     A a = new A(); 
     // why will m(Number) be called? 
     a.m(null); 
    } 
} 

UPDATE:其實是法數量實際上被調用。對此感到抱歉。

如果我調用a.m(null),它將使用Number參數調用方法。

我的問題是:這是爲什麼?在java語言規範中,這是指定的?

+1

...因爲'null'不是'Number'對象,因此它落入了更廣義的'Object'存儲桶。 – limc

+5

這很有趣,因爲在我的機器上(運行在日食)它alwways默認爲數字方法 –

+1

+1有趣的問題 –

回答

27

首先,它實際上叫m(Number)

這是因爲這兩種方法都適用,但m(Number)最具體方法,因爲m(Number)任何參數可以傳遞給m(Object),而不是相反。

如果您將m(Object)替換爲m(String)(或者添加其他方法,如m(Date)),編譯器會報告模糊性,因爲無法識別最具體的方法。

請參閱Java規範中的Choosing the Most Specific Method部分。

+2

好吧,現在我已經運行了示例代碼,我也看到了這一點。這也是有道理的,一旦我添加m(日期n){...},我得到一個錯誤:「方法m(對象)是模糊的類型」 – David

0

Object是Java中的默認類型。如果你重構你的m(Object o)方法m(String o)你就會有一個編譯時錯誤,指出該呼叫m(null)不明確,因爲Java的無法確定哪些StringNumber默認值之間的類null

除此之外,m(Object o)m(Number o)之間,呼喚m(null)將會撥打m(Number o),因爲它是最專業的方法。您需要將null轉換爲Object(或其他任何不是Number的實例)。

a.m((String) null); 
+0

null沒有類型,它打電話m(號碼) –

+0

以及..正式存在一個空類型,它是所有引用類型的子類型。很奇怪。 – irreputable

12
  1. 這不是多態或重寫。這是方法超載
  2. 我測試了這個,並調用了特定的方法(而不是m(Object)),並根據規範總是調用特定的方法。 Which overload will get selected for null in Java?
+2

+1注意覆蓋和超載之間的區別 –

+0

+1爲突出顯示這是超載 –

1

我的2美分。帶Number參數的方法是被調用的方法,因爲Number擴展了Object。在過去,我有過類似的情況,我沒有重寫一個方法,而是使用Component而不是JComponent(錯誤地)。我花了一個星期的時間才發現爲什麼我的方法從未被調用。我發現,如果重載方法之間存在某種繼承關係,則JVM首先匹配類層次結構中較深的一個。

7

你想想另一個相關的問題:

public static void main(String[] args) 
{ 
    A a = new A(); 
    Object n = new Integer(1); 
    a.m(n); // which method will be called? 
} 
+0

「m與對象稱爲」將被稱爲,但我不知道爲什麼。誰能解釋一下?直覺上,我認爲「m與號稱」會被打印出來,但是......不會。 – IsenGrim

0

捷豹,According to the Java Specifications,是的,它是一個對象。因此,主要使用Object參數類型中爲a.m(true)選擇的方法。

布爾在java.lang.Boolean中定義 在java.lang.Number中被定義數

(兩者延伸對象)

編碼員韻書:「當在煩惱,參考規格」