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.
b
and of type G
, b
anywhere where the variable b
is in scope. 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).