The call seems ambiguous, but works great with unexpected output

See this java class

class Demo { public static void a(String s) { System.out.println("string called"); } public static void a(Object a) { System.out.println("Object called"); } public static void main(String...asrgs) { a(null); } } 

The result of this code is called "string called", but I cannot understand how the compiler can resolve between Object and String .

Also view the code snippet

 class Demo { public static void a(String s) { System.out.println("string called"); } public static void a(Integer n) { System.out.println("number called"); } public static void a(Object a) { System.out.println("Object called"); } public static void main(String...asrgs) { a(null); } } 

Here we get a compile-time error related to an ambiguous call (which is quite obvious). Any good explanations for this?

+5
source share
1 answer

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) .

+5
source

Source: https://habr.com/ru/post/1203924/


All Articles