How to do method overloading for null argument?
Asked Answered
O

7

162

I have added three methods with parameters:

public static  void doSomething(Object obj) {
    System.out.println("Object called");
}

public static  void doSomething(char[] obj) {
    System.out.println("Array called");
}

public static  void doSomething(Integer obj) {
    System.out.println("Integer called");
}

When I am calling doSomething(null) , then compiler throws error as ambiguous methods. So is the issue because Integer and char[] methods or Integer and Object methods?

Ordure answered 8/3, 2011 at 7:55 Comment(4)
Just change the Integer to int.Strained
@Mudassir: and what exactly would that solve?Lashandralashar
@Joachim Sauer: If changed from Integer to int, then null isn't referred to primitive types in Java, so the compiler will not throw error.Ordure
@Joachim Sauer: It'll not throw the reference to doSomething is ambiguous error.Strained
L
254

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.

Lashandralashar answered 8/3, 2011 at 8:6 Comment(3)
This is stated for Java 7. Does that also apply to previous Java versions? I mean: If you have several method signatures with parameters only along a type hierarchy, than you are on the save side with null as actual value? And if you have built a "hierarchy for" like in the example here, then you are not?Humes
I'm pretty sure those rules are the same for at least everything since Java 1.1 (except for the addition of generics, obviously).Lashandralashar
Does this mean that if compiler were to choose in between doSomething(String str) and doSomething(Object obj) during runtime with doSomething(null), doSomething(String str) will be called.Reiff
A
56

Each pair of these three methods is ambiguous by itself when called with a null argument. Because each parameter type is a reference type.

The following are the three ways to call one specific method of yours with null.

doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);

May I suggest to remove this ambiguity if you actually plan to call these methods with null arguments. Such a design invites errors in the future.

Annabel answered 8/3, 2011 at 7:58 Comment(4)
Only Integer-char[] pair is ambiguous, because in other two cases, Java compiler can choose most specific choice, like @JoachimSauer described.Mcbee
@kajacx: OPs original question was about calling these methods with null as parameter. Under that precondition, all three pairs are ambiguous. For the general case, I agree that only Integer - char[] pair is ambiguous.Annabel
what about doSomething(null) for public static void doSomething(String str) { System.out.println("String called"); } This will return string called.Reiff
Is it possible to use an anotation like "nullable" or "not nullable" and set up the declarations so only the one method you want to get a null with so that an explicit "null" (yet implicit null type) argument always unambiguously selects a specific overload ??Woodprint
P
8

null is a valid value for any of the three types; so the compiler cannot decide which function to use. Use something like doSomething((Object)null) or doSomething((Integer)null) instead.

Pomelo answered 8/3, 2011 at 7:58 Comment(2)
I removed the method with Integer parameter, it's invoking the function and returning output as "Array Called", so what's the contract between Array and Object?Ordure
Java arrays are also Objects.Kirkland
L
2

Every class in Java extends Object class.Even Integer class also extends Object. Hence both Object and Integer are considered as Object instance. So when you pass null as a parameter than compiler gets confused that which object method to call i.e. With parameter Object or parameter Integer since they both are object and their reference can be null. But the primitives in java does not extends Object.

Lockage answered 8/3, 2011 at 8:5 Comment(0)
B
1

I Have tried this and when there is exactly one pair of overloaded method and one of them has a parameter type Object then the compiler will always select the method with more specific type. But when there is more than one specific type, then the compiler throws an ambiguous method error.

Since this is a compile time event, this can only happen when one intentionally passes null to this method. If this is done intentionally then it is better to overload this method again with no parameter or create another method altogether.

Burden answered 30/7, 2014 at 15:57 Comment(0)
D
0

there is an ambiguity because of doSomething(char[] obj) and doSomething(Integer obj).

char[] and Integer both are the same superior for null that's why they are ambiguous.

Dysteleology answered 4/11, 2017 at 0:41 Comment(0)
S
0
class Sample{
  public static void main (String[] args) {
       Sample s = new Sample();
       s.printVal(null);

    } 
    public static void printVal(Object i){
        System.out.println("obj called "+i);
    }

    public static void printVal(Integer i){
        System.out.println("Int called "+i);
    }
}

The output is Int called null and so ambiguity is with char[] and Integer

Shapely answered 4/8, 2018 at 13:14 Comment(1)
Do you have idea why this method will called public static void printVal(Object i){ System.out.println("obj called "+i); } Percy

© 2022 - 2024 — McMap. All rights reserved.