我有以下课程:
public class B {
public void print() {
}
public static void main(String[] args) {
B B = new B();
B.print();
}
}
我想知道为什么编译器没有给出错误说它不是静态方法。当我们将对象与类相同时,它将如何区分类级别和实例级别?
答案 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()
而不在类上调用。
无需说这是令人困惑的,应该在实际代码中避免使用;)