2009-10-09 90 views
3

如何在Java中實現方法覆蓋?在C++中,我們有vtable的概念。這是如何在Java內部實現的?在Java中覆蓋的方法

+0

Java沒有「功能」 - 它們被稱爲「方法」。 – Jesper 2009-10-09 11:20:13

+3

Answerers:OP特別詢問了**在Java中重寫的實現**(例如在編譯器或JVM本身中),而不是如何重寫代碼中的方法。 – Tim 2009-10-09 11:46:54

回答

12

要回答這個問題,具體如何在虛擬機中實現重寫,請參閱Programming for the Java Virtual Machine(Google圖書鏈接)。

虛擬機將在被引用的類中查找適當的方法定義,然後通過繼承堆棧繼續工作。顯然在某個階段會有各種優化。

用於相關字節代碼指令invokevirtual的描述見here

invokevirtual着眼於給定描述符 ,並且確定 多少個參數的方法接受 (這可以是零)。它從操作數棧中彈出這些 參數。接下來 它將objectref彈出堆棧。 objectref是對其方法被調用的對象 的引用。 invokevirtual檢索objectref Java類 ,並搜索列表中的某個類定義的方法 和 那麼它的超類,尋找 方法中調用方法名,其 描述符是描述符。

正如gustafc在下面強調的那樣,各種優化都可以應用,毫無疑問JIT將會進一步介紹。

+0

記住'invokevirtual'和'invokeinterface'調用實際上可以產生內聯代碼 - 如果被調用者僅由一個加載的類實現,則不需要搜索每個類的方法。如果有兩個類實現這些方法,那麼調用會被打入一個'if' /'else'來檢查對象的類型,這也比查找方法快。 – gustafc 2009-10-09 12:01:44

-1

只要您希望覆蓋的函數(方法)未標記爲final,您只需通過擴展包含該方法的類並提供具有相同簽名但方法不同的方法來覆蓋該方法。

+2

同樣,這是否解決了這個問題,但是,這是詢問內部實現(例如通過vtables或類似的)? – 2009-10-09 11:38:52

0

方法覆蓋 這意味着一個方法是在其中顯示了一些字符串晚飯類可用,但要擴展這個類,你也想在那個時候打印自己的方法,你需要重寫此方法到您的本地班。
這是重寫的基本介紹。

eg. 
class Animal 
{ 
    public void displayMessage() 
    { 
    System.out.println("Animal is eating"); 
    } 

} 
class Dog extends Animal 
{ 
    public void displayMessage() 
    { 
    System.out.println("Dog is eating"); 
    } 
    public static void main(String arg[]) 
    { 
    Dog d=new Dpg(); 
    d.displayMessage(); 
    } 
} 

OUTPUT:

狗正在抽穗方法覆蓋的

優點是類CA給自己的具體實現的方法繼承,沒有任何修改父類的方法。

方法重寫的規則是。

參數列表:參數列表必須相同。
訪問修飾符:如果您重寫該方法,則必須給出超類方法的相同修飾符,假設超類具有公共方法,則不能提供受保護或私有方法....等

0

在Java方法壓倒一切的是基於多態性OOPS 概念的概念,它允許程序員創建兩個方法與接口同名 和方法簽名和它不同的實施和 實際的方法被調用時根據運行類型的對象在 運行時。方法覆蓋允許您使用Java編寫靈活且可擴展的代碼 ,因爲您可以使用最少的 代碼更改來引入新功能。

在重寫Java中的任何方法時需要遵循的規則很少,不遵循這些規則會導致Java中的編譯時錯誤。

  1. 有關在Java中重寫方法的首要和最重要的規則是您只能覆蓋子類中的方法。你不能在同一個類中重寫方法。
  2. Java中方法重寫的第二個重要規則是方法的名稱和簽名必須在Super類和Sub類中或在接口及其實現中相同。
  3. 在Java中重寫方法的第三條規則是重寫方法不能減少Java中重載方法的可訪問性。例如,如果重寫方法是公共的,則重寫方法不能被保護,私有或包私有;但相反的是,覆蓋方法可以增加Java中方法的可訪問性,即如果重寫方法受保護,則重寫方法可以受保護或公開。
  4. 另一個值得注意的方法在Java中覆蓋的規則是覆蓋方法不能拋出層級高於重載方法的checked checked。這意味着如果重寫方法拋出IOException而不是重寫方法不能拋出java.lang.Exception在其throws子句中,因爲java.lang.Exception高於Exception Exception層次結構中的IOException。此規則不適用於Java中的RuntimeException,它甚至不需要在Java中的throws子句中聲明。
  5. 您不能覆蓋Java中的私有,靜態和最終方法。私有和靜態方法在編譯期間使用Java中的靜態綁定進行綁定,並且在運行時不會解析。在Java中重寫最終方法是編譯時錯誤。雖然私有和靜態方法可以隱藏,如果你在子類中聲明另一個具有相同和簽名的方法。
  6. 基於Object的類型,在運行時使用Java中的動態綁定調用重寫的方法。
  7. 如果您正在擴展抽象類或實現接口,則需要重寫所有抽象方法,除非您的類不是抽象類。抽象方法只能通過使用方法覆蓋來使用。
  8. 在Java中重寫方法時,始終使用@Override註釋。雖然這不是規則,但它是遵循最好的Java編程慣例之一。從Java 6開始,你也可以在從接口繼承的方法上使用@Override註解。