2012-10-17 25 views
11

在下面的代碼片段,想必看來,它應該發出一些編譯錯誤,但事實並非如此:使用一個內部類名和對象名稱在Java中相同

class Outer { 
    public static class Inner { 
     static String obj = "Inner"; 
    } 

    static Optional Inner = new Optional(); 
    //The (inner) class name and the object name are same. 
} 

class Optional { 
    String obj = "Optional"; 
} 

public class Main { 

    public static void main(String[] args) { 
     System.out.println(Outer.Inner.obj); 
     //Refers to the string inside the optional class 
    } 
} 

Outer有一個靜態的裏面的類名爲Inner。此外,它爲類定義Optionalstatic Optional Inner = new Optional();

這對象和類名(類Outer內部)是相同的,其是Inner的目的(靜態)。該程序顯示Optionalmain()中的唯一表達式Outer.Inner.obj預計會顯示Inner,但它不會。然而,實際輸出是Optional,這是Optional類的情況。

顯示Inner的一種方法是將對象名稱更改爲其他名稱。

static Optional Inner1 = new Optional(); 

從它顯示的輸出,看來對象名稱(或可變)被選擇在類型名稱(類Inner),因爲它們具有相同的名稱。這裏應用了什麼確切的案例?

回答

13

Paragraph 6.4.2 Java語言規範有關於在這種情況下適用的規則的一些信息。

一個簡單的名稱可能出現在上下文中,它可能會被解釋爲變量,類型或包的名稱。在這些情況下,§6.5的規則指定變量將優先於類型而被選擇,並且類型將優先於包來選擇。因此,有時可能不可能通過其簡單名稱來引用可見類型或包聲明。我們說這樣的聲明是被模糊的

這是指段落6.5 Determining the Meaning of a Name,其中詳細解釋了規則。

在您的示例中,Outer.Inner可能引用名爲Inner的嵌套類的類型或靜態成員變量Inner。規則說變量將被選擇在類型上。

3

其實類名是Outer $ Inner。

內部類實質上是Java 1.1中引入的一種黑客攻擊。 JVM實際上並沒有任何內部類的概念,因此編譯器必須避免它。編譯器生成AB「外」,但在相同的,然後將合成的存取/構造到它,以允許A得到它的訪問。

結帳以下職位:內部類的

Java inner class visibility puzzle

+0

+1非常好的答案! – GingerHead

+0

Downvoter關心評論? – GingerHead

+0

這確實是一個非常好的答案,這裏沒有提到這個問題。 – LuGo

2

想想其實也有自己的java文件。 這會讓你清楚爲什麼它選擇了Inner類的變量。

相關問題