I remember, the first time I used C#, being pleasantly surprised that 1.ToString() worked.
For a seasoned C# programmer, that might seem a bit silly: why wouldn't it work?
ToString works on every other value, except null, so why wouldn't I expect it work on a simple value like the number 1?
As you might have guessed from the title, it was only the low bar set by Java that allowed C# to create a feeling of delight while doing nothing but the obvious.
C# makes no distinction between a value and its boxed form, but in Java there's a sharp line between objects and primitives.
Primitives don't have methods.
1 is a primitive.
ToString is a method.
Therefore 1.toString() doesn't compile in Java.
Instead, you have to use the boxed form of int: say new Integer(1).toString().
This same basic story, of C# doing the obvious thing and Java doing the boilerplate thing, repeated itself with arrays and collections.
In C#, arrays implement interfaces like ICollection<T> and IEnumerable<T>.
In Java, you can't pass a String[] into a method asking for an Iterable<String> because String[] doesn't implement Iterable<String> or even Iterable.
Instead, just like with int, an adapter object is needed.
Perhaps the one returned by Arrays.asList?
Java 5 fixed most primitive-to-boxed-object-and-back boilerplate with autoboxing.
You still can't call toString on 1, but at least you can add 1 into a list.
Since the arrays-vs-collections thing is int-vs-Integer all over again, why not re-use the autoboxing solution?
Whenever a method asks for an Iterable<String>, and I pass a String[] instead, just have the compiler do the Arrays.asList call for me.
Wouldn't that be nice?
Well... probably. But it's also likely that, in ten years, I'd be complaining about it as a bad move.
Consider that exposing a byte[] as an iterable requires two levels of boxing.
The array has to be boxed into a collection, and then each byte item has to be boxed into a Byte.
This would be an unfortunate thing to do, when you're planning on adding value types to the language.
It would lock down byte[] as being an Iterable<Byte> instead of (possibly in the future) an Iterable<byte>.
Another issue that would crop up when autoboxing arrays, that isn't an issue for primitives, is the expectation of reference equality.
Programmers could reasonably expect that arr == (Iterable) arr should evaluate to true.
But arr != Arrays.asList(arr).
So that would be surprising and confusing.
Lastly, due to arrays' covariance (a design mistake that C# copied), the autoboxing is technically not type safe.
Code like Iterable<String> x = (String[]) (Object[]) new Byte[] {1, 2, 3} will produce a broken iterable (... I guess that already happens with Arrays.asList).
Summary
Twenty years ago, Java was created with unnecessary distinctions between primitives and objects.
We've been paying for it ever since, in IEnumerable ways.
