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.

Original source