How can one explain this seemingly inconsistent Java varargs behavior?
arrays, generics, java, variadic-functions
Solution
`Arrays.asList` is defined as having parameter `T...`, and the body will see it as one argument of type `T[]`. However, `T` must be a reference type (like any type parameter), and `int` is not a reference type. Because of that, there's no way to make `new int[]{...}` compatible with an array for varargs purposes. (And the result would be `List<int>` which isn't allowed.) The only alternative is to treat it as a single object, and thus `T` here will be `int[]`, which is a reference type, and the function will return a `List<int[]>`.
I think that's the reason, although I would still need to look up the exact language. It probably involves the type inference rules, which I haven't mastered.
However, I did try this:
List x = Arrays.asList(new int[]{1, 2, 3});
List y = Arrays.asList(new Integer[]{1, 2, 3});
System.out.println(x.size());
System.out.println(y.size());
(note that I deliberately used a `List` raw type, something I wouldn't do in real code). The output:
1
3
Problem
If I write the Java method ``` public static void f(int... x) { for (int a: x) { System.out.println(a); } } ``` then I can call this method via ``` f(1, 2, 3); ``` as well as ``` f(new int[]{1, 2, 3}); ``` and both calls are treated exactly the same. However, the two calls ``` Arrays.asList(1, 2, 3) // (a) produces a three-element Integer list ``` and ``` Arrays.asList(new int[]{1, 2, 3}) // (b) produces a one-element list of Integer arrays ``` are not treated the same. The section on evaluating arguments in the JLS states "The final formal parameter of m necessarily has type `T[]` for some `T`" so why isn't the "final formal parameter" in case (b) above not an integer array which would create a three-element list, like case (a)? The only thing I can think of is that `Arrays.asList` is generic, and something about type compatibility (mentioned in JLS Section 15.12.4.2) is at play here, but I can't quite put my finger on the actual sentence in the JLS that makes the two cases different. The commentary in the JLS talks about the need to craft these semantics carefully in order to handle the interplay between "parameterized types and array types that occurs in a Java Virtual Machine with erased generics" but what we end up is my function `f` and `Arrays.asList` appearing to behave inconsistent. In the former case I can "unpack" or "pack" my args and all is the same; in the latter case, the two cases are different. How is this explained in language-lawyer terms?