The answer lies in ยง15.12.2 JLS:
The second step searches for the type defined in the previous step for member methods. At this stage, the method name and argument expressions are used to search for available and applicable methods, i.e. Ads that can be correctly called for the given arguments.
There may be more than one such method, in which case the most specific one is chosen . The handle (type of signature and return) of the most specific method is the one that was used at run time to send the method.
(my emphasis)
... and ยง15.12.2.5 , to which the above section refers, which contains full information about the rules of specificity, but also this convenient summary:
An informal intuition is that one method is more specific than another if any call processed by the first method can be transferred to another without a compile-time error.
In your first example, a(String) more specific than a(Object) , so the compiler knows which one to use and is pleased. In your second example, both a(String) and a(Integer) more specific than a(Object) , but either apply to null and they are on separate lines ( String is String > Object , Integer is Integer > Number > Object ) creating the ambiguity that the compiler complains about.
If they were in the same line, there would be no ambiguity, because there would be the only applicable most specific option. For instance:
class Base { } class Child extends Base { } class GrandChild extends Child { } public class Example { public static final void main(String[] args) { a(null); } public static void a(Base b) { System.out.println("Base"); } public static void a(Child b) { System.out.println("Child"); } public static void a(GrandChild b) { System.out.println("GrandChild"); } }
This prints "GrandChild" because, although both a(Child) and a(GrandChild) more specific than a(Object) , a(GrandChild) more specific than a(Child) .