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).
The "best match" will be called. Objects are more precise than static methods, and as such object methods will be used by default; you can call a static method via Class.Method();
. What's actually wrong here is that your local variable b happens to have the same name as the class, and as such, it is hiding the class.
You can still call the class static method if you use the full path: Ambiguity.b.A();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With