2012-09-14 59 views
0

讓我們以下面的代碼:繼承的內部類的私有方法

public class Test { 

    class A { 
     public A() {} 

     private void testMethod() { 
      System.out.println("A"); 
     } 
    } 

    class B extends A { 
     public B() { super(); } 

     private void testMethod() { 
      System.out.println("B"); 
     } 
    } 

    public Test() { } 

    public A get() { 
     return new B(); 
    } 

    public static void main(String[] args) { 
     new Test().get().testMethod(); 
    } 
} 

我預計寫代碼B。代替寫入A

它可能會感到奇怪(至少對我來說)一個類可以調用它包含的內部類的私有方法(爲什麼他們這樣做?),但我真正無法理解的是爲什麼多態不起作用。

我的意思是,如果從Test.main()我們可以打電話A.testMethod()很明顯,我們也打電話B.testMethod()。 Java也可以確定一個對象的動態類型,爲什麼Java調用聲明類型的方法而不是動態類型?這種行爲可以被檢查:

public static void main(String[] args) { 
    B b = new Test().new B(); 
    A a = b; 
    b.testMethod(); // writes B 
    a.testMethod(); // writes A 
} 

另外,爲什麼會發生這種情況,只有當Test.A.testMethod()private

回答

3

它在JLS #15.2.3

定義,如果在編譯時聲明瞭private修飾符,然後調用模式非虛

而且JLS #15.4.4

如果調用模式是非虛擬的,不允許覆蓋。類T的方法m是要調用的方法。

哪裏T是聲明的類型,你的情況A,因爲(在你的情況B)而不是在運行時的實際類型的對象。換句話說,私有方法沒有多態性。

0

在Java中,所有非靜態方法默認爲「虛擬函數」。 兩種特殊的非靜態方法是非虛擬的:標有關鍵字final的 (不能被覆蓋),和 私有方法,這些方法不是繼承的

http://en.wikipedia.org/wiki/Virtual_function#Java

5

你期望的行爲源於虛方法。
私有方法永遠不是虛擬的。

相反,您有兩個不相關的方法碰巧具有相同的名稱。