解决静态方法歧义

时间:2015-02-19 23:16:07

标签: java compilation ambiguity

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

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();
    }
}

编译器如何知道天气来调用static void A()中的方法class bvoid A()类型的对象b上的常规方法G。根据我运行的测试,它似乎调用对象b(类型G)方法,但我不知道这是否始终是标准过程。在这种情况下,如何调用静态方法。

3 个答案:

答案 0 :(得分:6)

  • 局部变量,名为b,类型为G
  • 隐藏”类型b的名称,其中变量bin scope
  • 因此不会调用类型b上的方法。

模糊发生,因为本地范围的变量更具体。模糊的规则很复杂,但在JLS §6.4.2

中进行了总结
  

在上下文中可能会出现一个简单的名称,可能会将其解释为变量,类型或包的名称。在这些情况下,§6.5的规则指定变量将优先于类型,并且将优先选择类型与包。因此,有时可能无法通过其简单名称引用可见类型或包声明。我们说这样的声明是模糊的

这样的模糊是不好的做法,应该避免。但是,通过为类型提供限定名称§6.2),您可以解决这种情况的歧义。这会更改§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)。然后由§6.5.2的优先级规则重新分类(粗体是我的突出显示,斜体是我的补充):

  

如果AmbiguousName是一个简单的名称,由一个标识符

组成      

•如果标识符在局部变量声明(第14.4节)或参数声明(第8.4.1节,§8.8.1,§14.20)的范围(§6.3)内出现 )或具有该名称的字段声明(第8.3节),然后AmbiguousName被重新分类为ExpressionName ...而不是TypeName,来自较低优先级规则3 )。

答案 1 :(得分:1)

将调用“最佳匹配”。对象比静态方法更精确,因此默认情况下将使用对象方法;你可以通过Class.Method();调用静态方法。这里真正错误的是你的局部变量b恰好与类同名,因此它隐藏了类。

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

答案 2 :(得分:0)

在这种情况下,为了解决歧义,你应该致电:

Ambiguity.b.A();

Java优先考虑范围较小的变量。在这种情况下,Ambiguity.b实际上不是一个变量,但具有全局范围,因为它不属于实例对象。