12

How are these append() methods ambiguous?

public class Try_MultipleArguments {

    public static void main(String[] args) {

        int array1[] = new int[] {1, 2, 3};

        int array2[] = new int[] {4, 5, 6};

        append(array1, array2);

        append(array1, 4, 5, 6);

    }

    public static int[] append(int[] array1, int[] array2) {
        int[] ans = new int[array1.length + array2.length];
        for(int i=0; i<array1.length; ++i) {
            ans[i] = array1[i];
        }
        for(int i=0; i<array2.length; ++i) {
            ans[i+array1.length] = array2[i];
        }
        return ans;
    }

    public static int[] append(int[] array1, int ... array2) {
        return append(array1,array2);
    }
}

UPDATE

Varargs is equivalent to an array, but this is from inside of the method. From outside of the method it should not be equivalent to it.

UPDATE 2

I see now that I can pass an array to vararg. I didn't knew that. Was always workarounding this need. Hmmm.... Was this from the very beginning of java varargs?

Dims
  • 47,675
  • 117
  • 331
  • 600
  • See this answer http://stackoverflow.com/questions/3158730/java-3-dots-in-parameters – Md Johirul Islam Jul 03 '15 at 07:14
  • "From outside of the method it should not be equivalent to it.", please elaborate. – SamTebbs33 Jul 03 '15 at 07:16
  • Obviously these methods have same declaration. Why would this question get upvoted when it is a matter of googling syntax/reading compiler warning: Duplicate method append(int[], int[]) in type Try_MultipleArguments – John Jul 03 '15 at 07:16
  • `From outside of the method it should not be equivalent to it.` That's not true, at least not in Java. You can always pass in an array for a method expecting var-arg. – Adrian Shum Jul 03 '15 at 07:17
  • Yes, it is like that since varargs were introduced. The idea is to automate the step of creating an array for the programmer. – John Jul 03 '15 at 07:21
  • @user3360241 varargs is definitely NOT THE SAME as an array, because it ambiguate no-arg too... – Dims Jul 03 '15 at 07:24
  • From the varargs docs, you can see it is stated that they function in a same way for the outside world: In past releases, a method that took an arbitrary number of values required you to create an array and put the values into the array prior to invoking the method. It is still true that multiple arguments must be passed in an array, but the varargs feature automates and hides the process. @Dims true, i edited the comment. – John Jul 03 '15 at 07:25

5 Answers5

14

From the docs:

The three periods after the final parameter's type indicate that the final argument may be passed as an array or as a sequence of arguments.

So it's ambiguous because array also maps to the varargs.

inquisitive
  • 3,738
  • 6
  • 30
  • 56
7

The reason is because int... and int[] both accept an array of ints.

Let's take a look at what they accept:

int...

  • a list of integers (1, 2, 3, 4)
  • an array of integers ([1, 2, 3, 4])

int[]

  • an array of integers ([1, 2, 3, 4])

So the reason Java won't allow this is because both try to accept an array of integers. So it's not that they're the exact same thing.

A quick proof shows that this won't compile:

public static void main (String[] args) throws java.lang.Exception {
    test(1, 1, 1);
}

public static void test(int[] args) {

}

public static void test(int... args) {

}
Dave Chen
  • 10,887
  • 8
  • 39
  • 67
  • Now remove `test(int[] args)` and add `test()` (no-arg). You also won't compile. – Dims Jul 03 '15 at 07:18
  • But this proves that varargs IS NOT the same thing as an array. – Dims Jul 03 '15 at 07:21
  • I am noting that because I knew that `int...` is passing as an array, but since it was ambiguating no-arg, I was thinking, that compiler keeps separate signature for varargs. Now I see it is implemented more like a patch... – Dims Jul 03 '15 at 07:27
  • @DaveChen, in that case the compiler shouldn't also allow a no arg method... But it will... Because in the background a no arg call will result in the creation of an empty array and get passed to the vararg method... You can always print the size of the vararg variable and find out... – Codebender Jul 03 '15 at 07:31
  • Wow! I found that I am wrong here too: http://stackoverflow.com/questions/31201196/when-varargs-started-to-not-conflict-with-no-arg – Dims Jul 03 '15 at 07:38
  • @Dims Referring to your first comment, [it did compile](https://ideone.com/5cMMsl). But the logic still stands, both accept an array of ints. So it's ambiguous in that manner. – Dave Chen Jul 03 '15 at 07:42
7

They have the same definition.

In fact, int ... array2 is equivalent to int[] array2.

Burkhard
  • 14,596
  • 22
  • 87
  • 108
5

In the var args method, how do you use the variable array2.. Same as array right ??? It's the same actually, just denoted differently...

From the documentation,

It is still true that multiple arguments must be passed in an array, but the varargs feature automates and hides the process. Furthermore, it is upward compatible with preexisting APIs.

Codebender
  • 14,221
  • 7
  • 48
  • 85
  • 2
    More specifically, varargs is syntactic sugar for an array. Basically it tells the complier to create the array at the calling site (the same way optional parameters are handled in C#). – jmoreno Jul 03 '15 at 16:28
1

When defining a method with varargs, it can also be called using an array:

public static void method(int... array) {
    // do something with array
}

public static void caller1() {
    // This works obviously
    method(1, 2, 3);
}

public static void caller2() {
    // This works also
    method(new int[]{1, 2,, 3});
}

In fact in Java the two calls are analogous.

If you define another method with the array:

public static void method(int[] array)

Java won't know which method to call, because the call with array is already available.

For your case, it means that you can only have one signature:

public static int[] append(int[] array1, int ... array2)

and remove the other one.

superbob
  • 1,628
  • 13
  • 24