How Is an Overloaded Method Chosen When a Parameter Is the Literal Null Value

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



Leave a reply



Submit