2

I've got the following code:

public static void varargsMethod(String ... strings) {
    if (strings != null && strings.length != 0) {
        for (String s : strings) {
            System.out.println(s);
        }
    } else {
        System.out.println("Hello (string free) world!");
    }
}

public static void main(String[] args) {
    varargsMethod(null);
    varargsMethod((String[]) null);
    varargsMethod((String) null);
    varargsMethod();
}

I wonder why the first invocation with null as the argument generates a warning with the hint, that an explicit cast is needed. From the answers on this question it is not clear for me, why this cast is needed. The first two invocations work and produce the same result, while the third produces "null". I explicitly want the behaviour of the first two invocations.

Shouldn't null be always valid (and automatically casted) for reference types and arrays? I don't see, why the type information is important in this case.

Edit: Updated the code with a variant with no arguments at all. I definetly need to differ between the three cases (no array and empty array handled in the same way; array with null value in another). I wonder if there's a better way than checking for null and empty array.

Bengt
  • 3,798
  • 2
  • 21
  • 28
  • 1
    Doesnt the linked answer cover it? Since it cant decide if `null` is the array itself or the first value in the array. – Karthik T Aug 22 '13 at 01:14
  • I just edited my question. I would like to have `null` as the array instead of the first value. I believe it doesn't has to decide, because it's still possible to get the latter behaviour. – Bengt Aug 22 '13 at 01:18
  • Why would you *want* to pass in a null array? That sounds like a case where you'd want a `NullPointerException`. – user2357112 Aug 22 '13 at 02:08
  • Personally I don't want to pass in a null array myself. Nevertheless, I can't give a guarantee for future users. Shall I take care of this or is it ok, if they are punished with a NullPointerException on wrong usage? – Bengt Aug 22 '13 at 13:54

1 Answers1

3

It's just that null is implicitly convertible to any type, so in your case it's ambiguous. All of these are possible:

varargsMethod((String[])null); // pass in a null reference
varargsMethod(new String[]{null}); // pass in a single-element array
varargsMethod((String)null); // equivalent to previous

so the compiler is encouraging you to specify which one you mean.

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • Isn't `varargsMethod(null)` more clear (and less verbose) than casting it? Do you know if it's just a design decision or a technical reason? – Bengt Aug 22 '13 at 01:21
  • I'd say it's a technical reason – MadProgrammer Aug 22 '13 at 01:25
  • If your goal is to call with no parameters at all, an alternative method I prefer from a readability standpoint is to simply call `varagsMethod()`. It doesn't set strings to null, but rather to an empty array. Your varargsMethod can then be cleaned up a bit by leaving out null checks for strings (assuming you don't want users to be allowed to pass an explicitly cast null array) – helloworld922 Aug 22 '13 at 01:29
  • 2
    @Bengt: Actually, I think I would have expected that `varargsMethod(null)` meant `varargsMethod((String)null)`, since the point of a varargs method is that you can, and usually do, supply the elements of the array rather than the array itself. I've been assuming that the *only* reason it means `varargsMethod((String[])null)` is that the designers wanted strict backward-compatibility for any varargs methods that, before Java 5, used to take explicit array arguments, and that backward-compatibility required the implicit selection of `String[]` rather than the more-intuitive `String`. – ruakh Aug 22 '13 at 01:31
  • @helloworld922: Note that the OP's method is defined in such a way that passing a `null` array reference is *not* equivalent to passing in an empty array. (That's arguably a design mistake, though.) – ruakh Aug 22 '13 at 01:32
  • @ruakh: Thank you for pointing out that you expected I mean `(String)null`. I realized that null as the first argument does make more (or equivalent) sense. I just updated the question. Is there a better way to deal with the different ways of invoking the method? – Bengt Aug 22 '13 at 01:46
  • 1
    @Bengt: I think that if a null array is a valid use-case, then you don't actually want a varargs method. People think of varargs methods as taking a "variable number of arguments, maybe even zero" -- not "a variable number of arguments, or maybe some other option that's not a number of arguments at all". It's misleading to use varargs when you're really thinking of the array itself as the argument, such that null could make sense. – ruakh Aug 22 '13 at 02:33
  • @Bengt You're missing the point. You may find it clearer. The compiler just finds it ambiguous, under the resolution rules define din the JLS. – user207421 Aug 22 '13 at 03:19