当(在Java中)一个静态方法和一个同名的实例方法存在于不同的类中时,我无法访问该方法

当(在Java中)一个静态方法和一个同名的实例方法存在于不同的类中时,我无法访问该方法,java,static-methods,Java,Static Methods,首先,请看下面的代码 package test; class c_hi { public static void method_hi(){ System.out.println("hi"); } } class c_bye { public void method_hi(){ System.out.println("bye"); } } public class test { p

首先,请看下面的代码

package test;

class c_hi {
    public static void method_hi(){
        System.out.println("hi");
    }
}

class c_bye {
    public void method_hi(){
        System.out.println("bye");
    }
}

public class test {
    public static void main(String[] args){
        c_hi.method_hi();
        c_bye c_hi = new c_bye();
        c_hi.method_hi();
    }
}

我已经使用Java好几年了,我了解命名类名和变量名的一般规则

然而,我有一个非常有趣的问题。如果“c_bye”类的引用变量的名称为“c_hi”(名为“c_hi”的类已经存在)

我无法从类“test”内部访问类“c_hi”的“method_hi”

当然,我知道这个问题可以通过不重叠类名和变量名、包分离和FQCN等来防止或避免

除了避免重名的常用方法外,还有更符合语法的方法来解决这个问题吗?请告诉我你的意见。(或者,如果有任何关于堆栈溢出的文档、链接或其他问题可以参考,我将不胜感激。)

此代码对JDK版本8和15的工作原理相同。

这应该“修复”问题:

    test.c_hi.method_hi();  // Using the fully qualified class name.
然而,正确的解决办法是:

  • 不要忽略Java风格的规则。规则规定Java方法名应该以小写字母开头,类名应该以大写字母开头

  • 避免对静态方法和实例方法使用相同的名称

    (在某些情况下,您实际上无法执行此操作。例如,如果
    c_-bye
    扩展了
    c_-hi
    ,则您会得到一个编译错误,即不允许实例方法重写静态方法。)

  • 不要尝试使用实例变量调用静态方法。使用类名。(如果遵循样式规则,则不能将其与变量名混淆!)

    Java这样做是合法的,但它往往会愚弄读者,使他们认为该方法是一个实例方法和/或静态方法的动态调度正在发生

  • JLS中充分规定了名称解析规则的价值。(请参阅JLS文本和参考资料。)对于您正在讨论的边缘情况,其含义有点复杂,但名称解析规则不是特定于Java版本的


    当人们故意忽略样式规则时,Java并不是为了“玩得漂亮”而设计的。

    Java语言规范解决了这一问题。以下是JLS 6.4.2的第一段:

    简单名称可能出现在可能被解释为变量、类型或包的名称的上下文中。在这些情况下,的规则指定将优先选择变量而不是类型,并且将优先选择类型而不是包。因此,有时可能无法通过简单名称引用类型或包,即使其声明在范围内且未隐藏。我们说,这样一项声明是模糊的


    正如您已经提到的,必须使用FQN而不是简单的名称。

    最明显的是test.c_hi.method_hi();如果您使用标准Java命名约定,它将是
    classc_hi…
    classc_bye…
    C_bye C_hi=new C_bye()。“那就不会有混乱了。”吉姆加里森说。这就是命名约定和编译器的“名称阴影”警告的全部内容。正如mnesarco已经指出的,使用更限定的名称来解决这个“问题”。在这种情况下,它将是静态访问。动态访问也是一样:如果您在外部类COuter中的内部类CInner中,并且希望从CInner中访问COuter的方法/成员:您可以键入
    COuter.this.methodName()
    。或者,如果仍然存在名称隐藏问题,请包含完整的包名。关于OP的问题:是Java中的一种东西。适当地计划。完全限定“解决”了问题,但不会修复错误代码。没有理由这样写代码。