与类级别和实例级别混淆

时间:2010-02-18 17:10:42

标签: java

我有以下课程:

public class B {

    public void print() {
    }

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

}

我想知道为什么编译器没有给出错误说它不是静态方法。当我们将对象与类相同时,它将如何区分类级别和实例级别?

5 个答案:

答案 0 :(得分:5)

因为您正在访问类的实例上的方法。顺便提一下,实例的名称与类名相同,但由于您没有具有此名称的静态方法,因此编译器假定正确 - 即实例方法。

如果您将方法定义为static,那么它将再次假设唯一可能的事情 - 在static类上调用B方法,因为该实例没有这样的方法。

最终,您不能同时使用static和非static方法。

答案 1 :(得分:3)

JLS讨论并定义了此类案例的范围规则的优先级:

  

6.3.2模糊的声明

     

简单名称可能出现在它的上下文中   可能被解释为   变量的名称,类型或   包。在这些情况下,   §6.5的规则指定变量   将优先选择a   输入,并选择一种类型   优先于包裹。因此,它   有时可能是不可能的   指可见类型或包   声明通过简单的名称。我们   说这样的宣言是   模糊。

还有其他边框情况,其中变量可以阴影隐藏。例如:

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并根据规范解析名称。编译器不聪明,不会“弄清楚”任何东西,它只是遵循规范。

答案 2 :(得分: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

  }

}

答案 3 :(得分:0)

因为在该示例中,print()是实例方法。它是从B类实例调用的。如果你的主要看起来像这样:

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

然后print()必须是静态方法。

您的实例与该类的名称相同也无关紧要。由于print()是一个实例方法,因此它会从对象中调用它。只是碰巧你有一个名为B的对象,它是B类的一个实例。因此没有问题。

答案 4 :(得分:0)

我猜类名和实例变量不共享相同的命名空间;很明显,在实例上调用B.print()而不在类上调用。

无需说这是令人困惑的,应该在实际代码中避免使用;)