解决静态方法歧义
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()
].根据我 运行 的测试,它似乎调用对象 b
(G
类型)方法,但我不知道这是否始终是标准程序。这种情况怎么调用静态方法呢
- 局部变量,名称为
b
,类型为G
,
- “模糊了”变量
b
为 in 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 并不是一个真正的变量,而是具有全局范围,因为它不属于实例对象。
我一直在努力理解 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()
].根据我 运行 的测试,它似乎调用对象 b
(G
类型)方法,但我不知道这是否始终是标准程序。这种情况怎么调用静态方法呢
- 局部变量,名称为
b
,类型为G
, - “模糊了”变量
b
为 in 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 并不是一个真正的变量,而是具有全局范围,因为它不属于实例对象。