Resolving static method ambiguity
ambiguity, compilation, java
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).
Problem
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.