Calling Java varargs method with single null argument? Calling Java varargs method with single null argument? java java

Calling Java varargs method with single null argument?


The issue is that when you use the literal null, Java doesn't know what type it is supposed to be. It could be a null Object, or it could be a null Object array. For a single argument it assumes the latter.

You have two choices. Cast the null explicitly to Object or call the method using a strongly typed variable. See the example below:

public class Temp{   public static void main(String[] args){      foo("a", "b", "c");      foo(null, null);      foo((Object)null);      Object bar = null;      foo(bar);   }   private static void foo(Object...args) {      System.out.println("foo called, args: " + asList(args));   }}

Output:

foo called, args: [a, b, c]foo called, args: [null, null]foo called, args: [null]foo called, args: [null]


You need an explicit cast to Object:

foo((Object) null);

Otherwise the argument is assumed to be the whole array that the varargs represents.


A Test Case to illustrate this:

The Java code with a vararg-taking method declaration (which happens to be static):

public class JavaReceiver {    public static String receive(String... x) {        String res = ((x == null) ? "null" : ("an array of size " + x.length));        return "received 'x' is " + res;    }}

This Java code (a JUnit4 test case) calls the above (we are using the test case not to test anything, just to generate some output):

import org.junit.Test;public class JavaSender {    @Test    public void sendNothing() {        System.out.println("sendNothing(): " + JavaReceiver.receive());    }    @Test    public void sendNullWithNoCast() {        System.out.println("sendNullWithNoCast(): " + JavaReceiver.receive(null));    }    @Test    public void sendNullWithCastToString() {        System.out.println("sendNullWithCastToString(): " + JavaReceiver.receive((String)null));    }    @Test    public void sendNullWithCastToArray() {        System.out.println("sendNullWithCastToArray(): " + JavaReceiver.receive((String[])null));    }    @Test    public void sendOneValue() {        System.out.println("sendOneValue(): " + JavaReceiver.receive("a"));    }    @Test    public void sendThreeValues() {        System.out.println("sendThreeValues(): " + JavaReceiver.receive("a", "b", "c"));    }    @Test    public void sendArray() {        System.out.println("sendArray(): " + JavaReceiver.receive(new String[]{"a", "b", "c"}));    }}

Running this as a JUnit test yields:

sendNothing(): received 'x' is an array of size 0sendNullWithNoCast(): received 'x' is nullsendNullWithCastToString(): received 'x' is an array of size 1sendNullWithCastToArray(): received 'x' is nullsendOneValue(): received 'x' is an array of size 1sendThreeValues(): received 'x' is an array of size 3sendArray(): received 'x' is an array of size 3

To make this more interesting, let's call the receive() function from Groovy 2.1.2 and see what happens. It turns out that the results are not the same! This may be a bug though.

import org.junit.Testclass GroovySender {    @Test    void sendNothing() {        System.out << "sendNothing(): " << JavaReceiver.receive() << "\n"    }    @Test    void sendNullWithNoCast() {        System.out << "sendNullWithNoCast(): " << JavaReceiver.receive(null) << "\n"    }    @Test    void sendNullWithCastToString() {        System.out << "sendNullWithCastToString(): " << JavaReceiver.receive((String)null) << "\n"    }    @Test    void sendNullWithCastToArray() {        System.out << "sendNullWithCastToArray(): " << JavaReceiver.receive((String[])null) << "\n"    }    @Test    void sendOneValue() {        System.out << "sendOneValue(): " + JavaReceiver.receive("a") << "\n"    }    @Test    void sendThreeValues() {        System.out << "sendThreeValues(): " + JavaReceiver.receive("a", "b", "c") << "\n"    }    @Test    void sendArray() {        System.out << "sendArray(): " + JavaReceiver.receive( ["a", "b", "c"] as String[] ) << "\n"    }}

Running this as a JUnit test yields the following, with the difference to Java highlighted in bold.

sendNothing(): received 'x' is an array of size 0sendNullWithNoCast(): received 'x' is nullsendNullWithCastToString(): received 'x' is nullsendNullWithCastToArray(): received 'x' is nullsendOneValue(): received 'x' is an array of size 1sendThreeValues(): received 'x' is an array of size 3sendArray(): received 'x' is an array of size 3