Java varargs: inconsistent behaviour if you pass an array

In Java 1.4 there was the function Arrays.asList. You could pass it an array and it would make a list out of it.

String[] myArray = new String[] { "foo", "bar" };
List myList = Arrays.asList(myArray);

In Java 1.5 this was retrofitted for varargs; you could simply pass elements to the function

List<String> myList = Arrays.asList("foo", "bar");

I never really understood how that worked in a backwards-compatible way; I mean either the function takes an array of stuff, or it takes individual elements, surely?

It turns out, that with the varargs syntax, the caller is not forced to pass individual elements, the caller can instead pass an array of elements.

List<String> myList = Arrays.asList("foo", "bar");
List<String> myList = Arrays.asList(new String[] { "foo", "bar" });

The above two calls are identical, both return a List.

But surely this is really dangerous? I mean Arrays.asList does not make any assumptions about what types of arguments it accepts; the list can be composed of any object.

How can it be certain that you want to have an List of Strings, and not a List containing a single element which is a String array? (An array is an object.)

To demonstrate this inconsistency:

String[] arr = new String[] { "foo", "bar" };
Arrays.asList(arr);            // returns List<String>
Arrays.asList(arr, arr);       // returns List<String[]>
Arrays.asList(arr, arr, arr);  // returns List<String[]>
P.S. I recently created a nerdy privacy-respecting tool called When Will I Run Out Of Money? It's available for free if you want to check it out.

This article is © Adrian Smith.
It was originally published on 15 Apr 2010
More on: FAIL | Java | Language Design | Coding