2011-05-05 29 views
5

我有關於Java內部類的問題。與其他頂級類同名的Java內部類

有沒有一種方法可以從定義內部類A的頂級類Main中訪問頂級類A?

下面的示例代碼演示問題:

class A { // Outer Class A 
    { 
    System.out.println("A outer"); 
    } 
} 

class B { // Outer Class B 
    { 
    System.out.println("B outer"); 
    } 
} 

public class Main { 
    class A { // Inner Class A 
    { 
     System.out.println("A inner"); 
    } 
    } 

    public void newA() {  
    class A { // Local Class A 
     { 
     System.out.println("A local"); 
     } 
    } 
    new A(); 
    } 

    public static void main(String[] args) { 
    new Main().newA(); // prints "A local" 
    new Main().new A(); // prints "A inner" 
    //new A(); // compiler error: No enclosing instance of type Main is Accessible. 
    new B();  // but this works and prints "B outer" 
    } 
} 
+1

儘量在包之間重用類名。這很可能導致混淆。 – 2011-05-05 13:04:54

回答

9

使用完全合格的類名:

new com.mypackage.A(); 
4

如果類在包中,我期望這是實現這一目標的最簡單的方法。我不相信Java的C#global::有任何相當於強制這種事情。

但最終,我只是試圖改變類名,以避免首先發生問題。這通常比使用替代方法更好。

4

您應該爲兩個A s提供不同的軟件包名稱,以便它們明顯不同,然後可以按全名引用它們。

例如:

my.package.for.toplevel.A outerA = new my.package.for.toplevel.A(); // prints "A outer" 
                    // if this is the 
                    // package 

甚至更​​好,使用兩個不同的階級兩個不同的名字。

1

沒錯,只需使用包或避免從一開始命名他們一樣。我想知道你的理由是什麼?

爲了解釋你的錯誤,它來自它嘗試訪問內部A的事實,但由於該類沒有被聲明爲靜態的,並且沒有可用的主實例,所以它不能創建非靜態的內部A這需要參考父主實例。

+1

謝謝,我忘記了完全合格的類名稱技巧。 這個問題相當理論上與SCJP主題相關(不是真正的問題)。我試圖不使用這樣奇怪的結構:) – bary 2011-05-05 13:17:34

3

內部類的名稱被稱爲影響頂級類的名稱。在內部類的範圍內,頂級類不能被其簡單名稱引用;頂級類只能通過限定名稱引用。

如果頂級類位於默認包中(在這種情況下,其規範名稱與其簡單名稱相同),您仍然可以通過反射訪問它。

+0

「如果頂層類在默認包中(在這種情況下,其規範名稱與其簡單名稱相同),您仍然可以通過反射訪問它。」 你能舉一個快速的例子嗎? – 2012-09-12 22:30:47

+1

@TrevorDixon:您可以通過java.lang.Class.forName(String)或通過任何其他需要二進制名稱或該類的完全限定名稱的方法來訪問頂級類的類對象。例如,給定'class Name {class Name {/ * reference external class here * /}}',類型級別類型的Class對象可以通過Class.forName(「Name」)獲得。 – 2012-09-14 12:41:27

0

假設這些類都在默認包中。要在這種情況下解決命名衝突,需要重命名衝突的類或使用命名包。然後使用FQCN解決問題。