2009-09-26 91 views
1

以下接口和類已成功編譯。爲什麼Object類方法在接口中可用?

interface MyInterface{} 

class MyClass implements MyInterface{} 

class InterDoubt{ 

    static MyInterface mi ;//= new MyClass() ; 

    public static void main(String[] args){ 
     System.out.println("X") ; 

     try{ 
      synchronized(mi){ 
       try{ 
        mi.wait(4000) ; 
       } 
       catch(InterruptedException ie){ 
        System.out.println("Exception occured at main.") ; 
       } 
      } 
     } 
     catch(Exception e){ 
      System.out.println("voilla, MyInterface is an interface,\n" + 
         "then why compiler allows compilation of\n" + 
         "mi.getClass(), mi.wait().\n" + 
         "Or how the methods of Object class are available in an interface." 
      ); 
     } 

     System.out.println("Y") ; 
    } 
} 

輸出: 問題是在下面的輸出提到

X

voilla,MyInterface的是一個接口,

那麼爲什麼編譯器允許的彙編

mi.getClass(),mi.wait()。

或者如何在接口中使用Object類的方法。

Ÿ


編輯: - 我接受來自不認的答案,因爲它是最具解釋。但在閱讀答案後,還有一個問題得到填充: -

請記住,如果接口嘗試聲明Object類中聲明爲」final「的公共實例方法,則會導致編譯時錯誤。例如,'public final Class getClass()'是在Object類中聲明爲'final'的公共實例方法,因此如果一個接口試圖用這個簽名聲明一個方法,那麼編譯將失敗「(引自解釋)。

那麼爲什麼下面的代碼是越來越成功編譯: -

interface MyInter{ 
    public void method() ; 
} 

class MyClass implements MyInter{ 

    public final void method() { 
     ....... 
     ....... 
       ....... 
    } 

} 
+0

你確定嗎?當我嘗試這個(在Eclipse中)時,我得到一個錯誤,說變量mi可能沒有被初始化。 – CPerkins 2009-09-26 15:46:38

+0

另外,它不是引發異常的wait()調用。它是同步的(mi)。 – CPerkins 2009-09-26 15:49:24

+0

至於你的額外陳述 - 當然它編譯,因爲方法'方法'只是實現界面中聲明的內容。 JLS聲明所談論的是在「Object」類本身上聲明的方法。 – 2012-02-06 17:48:08

回答

5

在Java語言規範中指定了您正確指出的異常。接口將自動從類java.lang.Object中添加所有成員。從here

Java語言規範明確指出,一個接口的成員是那些在接口中聲明,以及那些從直接超接口繼承。如果一個接口沒有直接的超級接口,那麼接口將隱式聲明一個與Object類中聲明的每個公共實例方法相對應的公共抽象成員方法,除非具有相同簽名,相同返回類型和兼容throws子句的方法由該界面。這使得編譯器可以使用Object方法的簽名,並且代碼無任何錯誤地編譯。請記住,如果接口試圖在Object類中聲明一個聲明爲「final」的公共實例方法,那麼它將導致編譯時錯誤。例如,'public final Class getClass()'是在Object類中聲明爲'final'的公共實例方法,因此如果一個接口試圖用這個簽名聲明一個方法,那麼編譯將失敗。

2

在運行時應該有一個真正的對象(或空)參考MI後面。真正的類型將實現這個接口,因此編譯器允許它。在運行時,任何實現該接口的類型都可以在那裏。

+0

給定一個接口類型,一個實現該接口的具體類型,以及一個具體類型實例的接口引用,編譯器不允許你在接口中未指定的具體實例上調用方法。此外,對象方法根本不是任何(顯式)接口的一部分。 – 2009-09-26 15:04:41

0

是的,除Primitive值外,所有Object的方法都可用。接口對象仍然是對象,因此它們具有Object的方法。

+0

接口實例是_not_對象,它們只是委託對象的公共方法。 – 2009-09-26 15:06:21

+0

接口實例必須是對象。除原始值之外的所有東西都是對象。當你創建一個實例時,你需要從一個類創建(事實上,你用一個接口變量來保存它)。要創建一個實現對象的類,該類必須繼承某些東西(如果不指定它,該類將繼承Object)。這意味着每個實例(包括那些由接口變量保存的實例)總是對象。 – NawaMan 2009-09-26 15:55:15

+0

TYPO:「創建實現對象的類」=>「創建實現接口的類」。 :-p – NawaMan 2009-09-26 15:57:58

0

演員(對象)MI將始終成功,爲什麼你應該被要求提供呢?

0

Java語言規範明確指出,一個接口的成員是那些在接口中聲明,以及那些從直接超接口繼承。如果一個接口沒有直接的超級接口,那麼接口將隱式聲明一個與Object類中聲明的每個公共實例方法相對應的公共抽象成員方法,除非具有相同簽名,相同返回類型和兼容throws子句的方法由該界面。

+1

這是如何貢獻超過目前接受的答案(這正確地歸因於報價)? – 2012-02-06 18:59:23

相關問題