Choosing a Zero Value Overload Method

Given this code:

class Overloading extends Object { static public void target(Object val, String chk) { System.out.println("Object["+val+"] :: Should be "+chk); } static public void target(String val, String chk) { System.out.println("String["+val+"] :: Should be "+chk); } static public void main(String[] args) { Object obj=null; target(null ,"Object"); target((Object)null,"Object"); target(obj ,"Object"); } } 

the output (unexpectedly) is as follows:

 String[null] :: Should be Object Object[null] :: Should be Object Object[null] :: Should be Object 

The problem is the first line, which, I believe, will be the same as the other two. Also, I would swear that until recently, the compiler gave me an ambiguous call warning for a regular null call. However, compiling and testing using Java 5 and 6 give the same results.

This is a significant problem for me, since I have a lot of code that uses this template to use an overloaded "default" parameter of different types to select the return type and output the required conversion / parsing. Can anyone explain what is going on here?

+4
source share
2 answers

Java has always worked the same way: the "most specific" applicable overload is always selected. Since String is a subclass of Object , it is "more specific" and String overload is selected. If there were overloads, say String and Integer , and you tried to pass null , then you really get a compile-time ambiguity error, since both of them are on the same level with the same inheritance hierarchy.

+6
source

Remember that the null literal is of type "special null type" and not of type Object

A common confusion is that the null literal is of type Object , which leads people to believe that the nearest consistent signature is target(Object val, String chk) .

The literal null is actually of type "[special null type]" ( Java Language Spec (JLS) 4 ). If such a method could be defined, the closest match would be target([special null type] val, String chk) .

However, since there is no such method (you could not create it), the compiler searches for the closest match through subtyping ( JLS 15.12. 2.2 ). The direct supertype of [special null type] is all reference types ( JLS 4.10.2 ) (for example, String), and Object is the supertype of String.


Perhaps a more intuitive way to look at this is through the intuitive definition of JLS for the “most concrete method” ( JLS 15.12.2.5 )

"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 compilation type error."

Of the two methods that the call to target(null ,"Object") answers, any call

 void target(String val, String chk) 

can be processed

 void target(Object val, String chk) 

therefore, intuitively void target(String val, String chk) is the “most specific” that could be called without a type error.

See JLS 15.12.2.5 for how “the most specific” is formally defined.

+3
source

All Articles