2013-04-06 72 views
-1

生效:選擇哪個重載調用是在編譯時進行的。 實施例:使用重載vs覆蓋,編譯時間vs運行時間

class parentsecond{ 
    public int getdouble(int x){ return x*2;} 
} 
class second extends parentsecond{ 
    public int getdouble(int x){ return x*3;} 
} 
class third{ 
    public static void calloverload(parentsecond s){ 
     System.out.println(s.getdouble(4)); 
    } 
    public static void calloverload(second s){ 
     System.out.println(s.getdouble(4)); 
    } 

    public static void main(String[] args){ 
     third t=new third(); 
     parentsecond s=new second(); 
     t.calloverload(s); 
    } 

} 

回答是12. 並且行爲爲實例方法重載的方法相同的太。因此,在任何一種情況下,調用哪個重載方法的決定都是在運行時而不是編譯時(它總是被調用的'second''getdouble)進行的。

因此,對於'Effective Java'中的這個特定項目有一些限制,我沒有得到。

請幫助澄清'在編譯時解決超載'的含義。

如何從這個上面不同:

.... 

    class fourth{ 

      public static String getCollection(Set<?> s){ 
       return "Set"; 
      } 
      public static String getCollection(Collection<?> c){ 
       return "Collection"; 
      } 

      public String getiCollection(Set<?> s){ 
       return "Set"; 
      } 
      public String getiCollection(Collection<?> c){ 
       return "Collection"; 
      }  

      public static void main(String[] args){ 

       Collection<String> c=new HashSet<String>(); 
       System.out.println(fourth.getCollection(c)); 
       fourth f=new fourth(); 
       System.out.println(f.getiCollection(c)); 
... 

這個答案在這種情況下,始終是「收集」,而不是實際的運行時類型。

+3

你能澄清你的問題嗎? – 2013-04-06 02:32:09

+3

問題是什麼? – Buddha 2013-04-06 02:32:54

+0

重新說明了問題,使其更清晰 – IUnknown 2013-04-06 02:37:24

回答

2

聲明類型的sparentsecond所以當編譯器通過代碼運行時,它將分配該取parentsecond作爲參數

public static void calloverload(parentsecond s)... 

然而,首要的是一個不同的主題的方法。實例s的實際類型爲second,因此將執行secondgetdouble方法。這是一個多態的例子。在java中,多態性是通過late-binding完成的。

要從this answer:

引述JLS狀態在§8.4.9超載:

  1. 當一個方法被調用(§15。12)中,實際參數(以及任何顯式類型參數)的數量和參數的編譯時類型在編譯時用於確定將被調用的方法的簽名(第15.12.2節)。
  2. 如果要調用的方法是實例方法,則將在運行時使用動態方法查找(第15.12.4節)確定要調用的實際方法。

參數是s,其編譯時間類型是parentsecond。它的運行時間類型是second

編輯要回答您的問題,請參閱上面的第1點。在運行時不需要評估任何內容。編譯器在兩次調用中都使用編譯時類型Collection

+0

現在有了完美的意義。當我打印出哪個重載的'calloverload'版本被調用時 - 它確實是接受父對象的ne。然後在傳入類的運行時版本上調用getdouble。 – IUnknown 2013-04-06 03:22:28

+0

@IUnknown我很高興這有幫助。你應該聽聽_Russell_下面說的。重載方法時,儘量不要使用子類型。 – 2013-04-06 03:23:21

0

重點不在於編譯器無法搞清楚;問題在於超載對程序員來說是令人困惑的,因此可能會導致錯誤。

如果您需要抽出JLS來確定哪種方法與您調用方式最匹配,那麼每個查看該代碼的維護程序員都必須經歷相同的練習。

因此,建議重載應該有不同數量的參數,或至少不可互換的參數類型。

「解決編譯時重載」的具體危險是這樣的。假設我有:

void method(List a) { } 
void method(Collection a) { } 

然後,這兩個調用會做不同的事情:

List list = new ArrayList(); 
method(list); 
method((Collection)list); 

這是非常直觀的程序員(因此混亂,因而是錯誤的來源)。

+0

編輯該問題以進一步澄清。 – IUnknown 2013-04-06 03:10:16