我有下面的類:混亂與類級別和實例級別
public class B {
public void print() {
}
public static void main(String[] args) {
B B = new B();
B.print();
}
}
我想知道爲什麼編譯器沒有給出一個錯誤,說這不是一個靜態方法。當我們將對象與類相同時,它將如何區分類級別和實例級別?
我有下面的類:混亂與類級別和實例級別
public class B {
public void print() {
}
public static void main(String[] args) {
B B = new B();
B.print();
}
}
我想知道爲什麼編譯器沒有給出一個錯誤,說這不是一個靜態方法。當我們將對象與類相同時,它將如何區分類級別和實例級別?
因爲您正在訪問類的實例上的方法。順便提一下,實例的名稱與類名相同,但由於您沒有具有此名稱的靜態方法,編譯器會採用正確的方式 - 即實例方法。
如果將方法定義爲static
,那麼它將再次假定唯一可能的事情 - 在B
類上調用static
方法,因爲該實例沒有這種方法。
最終,您不能同時使用同名的static
和非static
方法。
因爲在那個例子中,print()
是一個實例方法。它正在從B類的實例調用如果你的主是這樣的:
public static void main(String[] args){
print():
}
然後print()
必須是一個靜態方法。
您的實例與類名稱相同也無關緊要。由於print()
是一個實例方法,因此它會期望從一個對象中調用它。只是碰巧你有一個名爲B的對象,它是類B的一個實例。所以沒有問題。
你的問題是關於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
}
}
我猜類名和實例變量不共享相同的命名空間;對編譯器來說,顯然B.print()
在實例上被調用,而不是在類上調用。
沒有必要說,這是混亂的,應在實際的代碼是可以避免的;)
的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並根據規範解析名稱。編譯器不聰明,不會「弄清楚」任何東西,它只是遵循規範。
B對編譯器很好! – JRL 2010-02-18 17:14:23
有趣的問題!我從來沒有見過任何人討論過與同級別的同名同名對象... – froadie 2010-02-18 17:21:00
但應該指出,這種風格被認爲是不好的做法。變量應該命名爲小寫。應避免使用除循環索引之外的單字符標識符。另請參閱http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html#367 – BalusC 2010-02-18 17:24:40