Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the output like this?

class Another {
    public void method(Object o) {
        System.out.println("This is in method which takes object");
    }
    public void method(String s) {
        System.out.println("This is method which takes string");
    }
}

public class NewClass {
    public static void main(String args[]) {
        Another an = new Another();
        an.method(null);
    }
}

When I try to execute this, I get

This is method which takes string

as the output. Why not "This is in method which takes object"? Object can also be null and string can also be null, why doesn't it invoke first method?

like image 328
Chetan Avatar asked Jun 14 '10 12:06

Chetan


3 Answers

According to the Java Language Specification, in such cases of overloaded methods where both methods can handle the provided arguments, the method with more specific argument is chosen. Since String is more specific than Object (String extends Object), void method(String) is chosen and called.

like image 63
Abhinav Sarkar Avatar answered Sep 28 '22 07:09

Abhinav Sarkar


This is exactly as specified in JLS:

JLS 15.12.2.5 Choosing the Most Specific Method

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.

A String is-a Object, but not all Object is-a String. Therefore, String is more specific than Object, hence why the String overload is chosen in the above example.


It is worth noting that this exact question (in essence) appeared in the wonderful Java Puzzlers (highly recommended), specifically Puzzle 46: The Case of the Confusing Constructor

Java's overload resolution process operates in two phases. The first phase selects all the methods or constructors that are accessible and applicable. The second phase selects the most specific of the methods or constructors selected in the first phase. One method or constructor is less specific than another if it can accept any parameters passed to the other

The key to understanding this puzzle is that the test for which method or constructor is most specific does not use the actual parameters: the parameters appearing in the invocation. They are used only to determine which overloadings are applicable. Once the compiler determines which overloadings are applicable and accessible, it selects the most specific overloading, using only the formal parameters: the parameters appearing in the declaration.


I will close with a quote from Effective Java 2nd Edition, Item 41: Use overloading judiciously:

The rules that determine which overloading is selected are extremely complex. They take up thirty-three pages in the language specification, and few programmers understand all of their subtleties.

Needless to say, this book is also highly recommended.

See also

  • Polymorphism vs Overriding vs Overloading
  • Method Overloading. Can you overuse it?

On explicit casting

So how can I invoke the Object overload with null argument?

Simple: cast the null to type Object. There are several scenarios where this is useful/necessary, and this is one of them.

What if I have an overload that takes, say, an Integer?

Then the method invocation is ambiguous, and compile-time error occurs.

JLS 15.12.2.5 Choosing the Most Specific Method

It is possible that no method is the most specific, because there are two or more methods that are maximally specific. In this case [... with some exceptions] we say that the method invocation is ambiguous, and a compile-time error occurs.

To resolve the ambiguity, again you can cast the null (or other expression) to the desired overload type.

See also

  • JLS 15.12.2.10 Example: Overloading Ambiguity
like image 24
polygenelubricants Avatar answered Sep 28 '22 08:09

polygenelubricants


The compiler will always find the narrowest match possible when resolving overloaded method calls.

Btw the Java convention is to use uppercase names for classes, i.e. Another.

like image 29
Péter Török Avatar answered Sep 28 '22 08:09

Péter Török