Search code examples
javacompilationambiguity

Resolving static method ambiguity


I have been working on understanding java compilation and I have come across a question. Say we have a class set up like this

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

How does the compiler know weather to call the method static void A() in the class b or the regular method void A() on the object b of type G. Based on tests I ran it appears to call the object b (of type G) method but I did not know if this is always standard procedure. In this situation how could the static method be called.


Solution

    • The local variable, named b and of type G,
    • "obscures" the name of the type b anywhere where the variable b is in scope.
    • The method on the type b is therefore not called.

    The obscuring occurs as the local scoped variable is more specific. The rules for obscuring are complex, but summarised in 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.

    Obscuring like this is bad practice and should be avoided. However you can work around the ambiguity in this case by providing a qualified name (§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
    

    Prints:

    Static Method
    Regular Method

    ~~~~

    Specifically, the unqualified name b in this context is classified initially as an Ambiguous Name (§6.5.1). It is then reclassified by the priority rule from §6.5.2 (bold is my highlighting, italics is my addition):

    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).