How is an overloaded method chosen when a parameter is the literal null value?
Is null a String variable pointing to nothing ?
A null reference can be converted to an expression of any class type. So in the case of String
, this is fine:
String x = null;
The String
overload here is chosen because the Java compiler picks the most specific overload, as per section 15.12.2.5 of the JLS. In particular:
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 type error.
In your second case, both methods are still applicable, but neither String
nor StringBuffer
is more specific than the other, therefore neither method is more specific than the other, hence the compiler error.
Using null in overloaded methods in Java
If you were asked what is more specialized "String" or "Object", what would you say? Evidently "String", right?
If you were asked: what is more specialized "String" or "Integer"? There is no answer, they are both orthogonal specializations of an object, how can you choose between them? Then you must be explicit regarding which one you want. For instance by casting your null reference:
question.method((String)null)
When you use primitive types you do not have that problem because "null" is a reference type and cannot conflict with primitive types. But when you use reference types "null" could refer to either String or Integer (since null can be cast to any reference type).
See the answer in the other question that I posted in the comments above for further and deeper details and even a few quotes from the JLS.
Passing null as argument in overloaded methods?
You need to cast null
to the type you want so that the compiler can resolve the ambiguity.
For example:
PersonFactory.get("John", "Doe", (String) null);
or
PersonFactory.get("John", "Doe", (Integer) null);
Method overloading related: when null is passed as a paramater
The method having most specific / least generic type is chosen. Object
is the superclass of all other classes, so, in the first case, int[] intArray
method is chosen.
In the second case, you have 2 types at the same level, this will cause compilation problems. You cannot have String
and StringBuilder
because they are at the same level in the class hierarchy. You can have Exception
, IOException
because they are at different levels.
null
can be passed to any method that takes a reference type as argument, but at the same time you need to ensure that you don't have methods that take types that are at the same level.
Overloading null ambiguity
The problem is that both string
and object
are nullable, so null
could refer to either overload of the method. You have to cast the null value—as stupid as that sounds—to say explicitely which overload you want to call.
method("string", (string) null);
method("string", (object) null);
This is basically the same as if you defined a variable of either type and passed that then:
string param1 = null;
object param2 = null;
method("string", param1); // will call the string overload
method("string", param2); // will call the object overload
Both param1
and param2
have the same value, null
, but the variables are of different types which is why the compiler is able to tell exactly which overload it needs to use. The solution above with the explicit cast is just the same; it annotates a type to the null
value which is then used to infer the correct overload—just without having to declare a variable.
Why is overloaded method selected with direct superclass parameter rather than Object?
Overloading will resolve to the most specific type that applies to the argument. All of A
, B
and Object
could apply to C
, but the most specific of those is B
. So method(B)
will be called.
If C
did not extend A
or B
, then method(Object)
would be called.
How to do method overloading for null argument?
Java will always try to use the most specific applicable version of a method that's available (see JLS §15.12.2).
Object
, char[]
and Integer
can all take null
as a valid value. Therefore all 3 version are applicable, so Java will have to find the most specific one.
Since Object
is the super-type of char[]
, the array version is more specific than the Object
-version. So if only those two methods exist, the char[]
version will be chosen.
When both the char[]
and Integer
versions are available, then both of them are more specific than Object
but none is more specific than the other, so Java can't decide which one to call. In this case you'll have to explicitly mention which one you want to call by casting the argument to the appropriate type.
Note that in practice this problem occurs far more seldom than one might think. The reason for this is that it only happens when you're explicitly calling a method with null
or with a variable of a rather un-specific type (such as Object
).
On the contrary, the following invocation would be perfectly unambiguous:
char[] x = null;
doSomething(x);
Although you're still passing the value null
, Java knows exactly which method to call, since it will take the type of the variable into account.
Related Topics
Best Way to Compare 2 Xml Documents in Java
How to Fix Role in Spring Security
How to Get the Current Time in Yyyy-Mm-Dd Hh:Mi:Sec.Millisecond Format in Java
Controlling Maven Final Name of Jar Artifact
Where Is Java_Home on MACos Mojave (10.14) to Lion (10.7)
Is It a Bad Practice to Catch Throwable
Extract Digits from a String in Java
Embed Java into a C++ Application
Android 6.0 Open Failed: Eacces (Permission Denied)
Is System.Nanotime() Completely Useless
Certain Unix Commands Fail with "... Not Found", When Executed Through Java Using Jsch
Keyword for the Outer Class from an Anonymous Inner Class
Differencebetween "Class.Forname()" and "Class.Forname().Newinstance()"