解决静态方法歧义

Resolving static method ambiguity

我一直在努力理解 java 编译,我遇到了一个问题。假设我们有一个 class 这样的设置

public class Ambiguity 
{
    static class G
    {
        void A()
        {
            System.out.println("Regular Method");
        }
    }

    static class b
    {
        static void A()
        {
            System.out.println("Static Method");
        }
    }

    public static void main(String[] args)
    {

        G b = new G();
        b.A();
    }
}

编译器如何知道天气如何调用 class b 中的方法 static void A() 或 [=15= 类型的对象 b 上的常规方法 void A() ].根据我 运行 的测试,它似乎调用对象 bG 类型)方法,但我不知道这是否始终是标准程序。这种情况怎么调用静态方法呢

  • 局部变量,名称为b,类型为G
  • 模糊了”变量 bin scope 的任何地方类型 b 的名称。
  • 因此不调用类型 b 上的方法。

模糊 发生在局部作用域变量更具体时。模糊规则很复杂,但总结在 JLS §6.4.2:

A simple name may occur in contexts where it may potentially be interpreted as the name of a variable, a type, or a package. In these situations, the rules of §6.5 specify that a variable will be chosen in preference to a type, and that a type will be chosen in preference to a package. Thus, it is may sometimes be impossible to refer to a visible type or package declaration via its simple name. We say that such a declaration is obscured.

像这样模糊是不好的做法,应该避免。但是,在这种情况下,您可以通过提供 限定名称 (§6.2) for the type. This changes the applicable name selection rule from §6.5:

来解决歧义
G b = new G();
Ambiguity.b.A(); // calls Ambiguity.b.A()
b.A();           // calls Ambiguity.G.A() on variable b

打印:

Static Method
Regular Method

~~~~

具体来说,在此上下文中的非限定名称 b 最初被归类为 不明确的名称§6.5.1). It is then reclassified by the priority rule from §6.5.2(粗体是我的突出显示,斜体是我的添加):

If the AmbiguousName is a simple name, consisting of a single Identifier

• If the Identifier appears within the scope (§6.3) of a local variable declaration (§14.4) or parameter declaration (§8.4.1, §8.8.1, §14.20) or field declaration (§8.3) with that name, then the AmbiguousName is reclassified as an ExpressionName (... as opposed to a TypeName, from the lower priority rule 3).

"best match" 将被调用。对象比静态方法更精确,因此默认使用对象方法;您可以通过 Class.Method(); 调用静态方法。这里的实际错误是您的局部变量 b 恰好与 class 同名,因此它隐藏了 class。

如果使用完整路径,您仍然可以调用 class 静态方法:Ambiguity.b.A();

在这种情况下,要解决歧义,您应该调用:

Ambiguity.b.A();

Java 优先选择作用域较小的变量。在这种情况下,Ambiguity.b 并不是一个真正的变量,而是具有全局范围,因为它不属于实例对象。