0

In java, I have 2 methods which are overloaded and one is main method, so from the main method I call the overloaded method.

public class Test {
public static void main(String[] args) throws IOException {
    doSomething(null);
}
private static void doSomething(Object o) {
    System.out.println("method with Object in signature is called.");
}
private static void doSomething(String s) {
    System.out.println("method with String in the signature is called.");
}
}

Here when I run this java code, it will call the doSomething(String s) method and it will print

method with String in the signature is called.

I think it will call doSomething(Object o) method, but it won't happen.

So can anyone explain to me this in greater detail, why this has happened and how?

Thank you.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
Dhaval Bhoot
  • 241
  • 1
  • 5
  • 18

3 Answers3

8

From JLS 15.12.2.5 (emphasis added):

If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.

The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error.

Anything that can be passed to the String method can be passed to the Object method too, whilst there are things you can pass to the Object method that can't be passed to the String method (e.g. new Object()) (*); so the String method is more specific, so that is the one that is chosen.


(*) This clause is important: if you replaced the Object method with, say:

private static void doSomething(Integer s) {

then there would be things you could pass to doSomething(String) that you couldn't pass to doSomething(Integer); and there would be things you could pass to doSomething(Integer) that you couldn't pass to doSomething(String). In that case, neither is more specific, so the method invocation would be considered ambiguous.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • I was just about to suggest the edit you just made! – TripeHound Jan 21 '20 at 13:36
  • `doSomething(String)` and `doSomething(Integer)` are _not_ ambiguous, as no String ever could be passed as Integer and no Integer ever could be passed as String. – Amadán Jan 21 '20 at 13:52
  • @Amadán `doSomething(null)` [would be ambiguous](https://ideone.com/qjurb3). And it's ambiguous precisely because "no String ever could be passed as Integer and no Integer ever could be passed as String". – Andy Turner Jan 21 '20 at 13:53
  • @AndyTurner that is correct. But it would be the same with `doSomething(Object)` and `doSomething(String)`. – Amadán Jan 21 '20 at 13:55
  • @Amadán no. Please read my answer carefully, and [try it](https://ideone.com/S004lt). – Andy Turner Jan 21 '20 at 13:55
  • @AndyTurner Okay. I learnt something today, thanks. But I suggest you edit your answer to clearify that you're talking about the null parameter scenario! Also I think one should rather avoid overloading. It is source for too much confusion. – Amadán Jan 21 '20 at 14:05
  • Yes, I tried to implement, if I make the method doSomething(Integer i) instead of doSomething(Object o), and eclipse show an error of saying "The method doSomething(Integer) is ambiguous for the type Test" – Dhaval Bhoot Jan 21 '20 at 14:07
  • @AndyTurner Thanks for the reply. I am trying to understand your response, but it is in little difficult to understand. Can you explain it in simple terminology? – Dhaval Bhoot Jan 21 '20 at 14:10
  • @DhavalBhoot In the original case (`Object` vs `String`), _anything_ can be passed to the `Object` overload, but only _some_ things (`Strings` and `null`) can be passed to the `String` overload. Therefore that is the more specific version, and anything that _can_ be passed to the `String` overload will be (and anything that _cannot_ be passed to the `String` overload will be passed to the `Object` overload). – TripeHound Jan 21 '20 at 16:23
  • @DhavalBhoot In the case of `Integer` vs. `String`, neither is more specific, because the domain of one (i.e. what can be passed-in) is not a _subset_ of the domain of the other (as is the case with `String` vs. `Object`). – TripeHound Jan 21 '20 at 16:27
1

In Java always the more specific version of method is chosen over the generic one. If the passed parameter is of type String then it will always use method with String parameter rather than generic object one.

Lav
  • 1,850
  • 15
  • 17
0

Java follows early binding approach so during compile time it chooses the most specific method.most specific method is chosen by matching a number of parameters and type of parameter in case of method overloading.here in your case to resolve the method call type of parameter is used to resolve method call since number of parameter are equal in both methods.

k_23
  • 11
  • 2