2010-02-18 87 views
3

我有下面的類:混亂與類級別和實例級別

public class B { 

    public void print() { 
    } 

    public static void main(String[] args) { 
     B B = new B(); 
     B.print(); 
    } 

} 

我想知道爲什麼編譯器沒有給出一個錯誤,說這不是一個靜態方法。當我們將對象與類相同時,它將如何區分類級別和實例級別?

+3

B對編譯器很好! – JRL 2010-02-18 17:14:23

+0

有趣的問題!我從來沒有見過任何人討論過與同級別的同名同名對象... – froadie 2010-02-18 17:21:00

+5

但應該指出,這種風格被認爲是不好的做法。變量應該命名爲小寫。應避免使用除循環索引之外的單字符標識符。另請參閱http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html#367 – BalusC 2010-02-18 17:24:40

回答

5

因爲您正在訪問類的實例上的方法。順便提一下,實例的名稱與類名相同,但由於您沒有具有此名稱的靜態方法,編譯器會採用正確的方式 - 即實例方法。

如果將方法定義爲static,那麼它將再次假定唯一可能的事情 - 在B類上調用static方法,因爲該實例沒有這種方法。

最終,您不能同時使用同名的static和非static方法。

0

因爲在那個例子中,print()是一個實例方法。它正在從B類的實例調用如果你的主是這樣的:

public static void main(String[] args){ 
     print(): 
     } 

然後print()必須是一個靜態方法。

您的實例與類名稱相同也無關緊要。由於print()是一個實例方法,因此它會期望從一個對象中調用它。只是碰巧你有一個名爲B的對象,它是類B的一個實例。所以沒有問題。

2

你的問題是關於print()方法?它的作用是因爲你的變量名稱是「隱藏」類型名稱,所以當你做B.print()時,它會查看變量B,它是類B的一個實例。

你真的不應該打電話給你變量與類相同的名稱,至少不是相同的情況。如果你重命名變量,即使只是'b',情況會更清楚。所以:

public class B{ 

    public void print(){ 

    } 

    public static void main(String[] args){ 

    B b = new B(); 

    b.print(); // This works 
    B.print(); // this fails 

    } 

} 
0

我猜類名和實例變量不共享相同的命名空間;對編譯器來說,顯然B.print()在實例上被調用,而不是在類上調用。

沒有必要說,這是混亂的,應在實際的代碼是可以避免的;)

3

JLS討論和定義作用域規則,這種情況下的優先級:

6.3.2遮住聲明在上下文中,其中它 可以潛在地解釋爲變量,類型或 包的 名稱可能發生

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

還有其他的邊界情況下,當變量可以是陰影隱藏。示例:

class Test { 
     static int x = 1; 
     public static void main(String[] args) { 
       int x = 0; 
       System.out.print("x=" + x); 
       System.out.println(", Test.x=" + Test.x); 
     } 
} 

此外,編譯器遵循JLS並根據規範解析名稱。編譯器不聰明,不會「弄清楚」任何東西,它只是遵循規範。