The JavaScript exception "is not iterable" occurs when the value which is given as the right-hand side of for...of , as argument of a function such as Promise. all or TypedArray. from , or as the right-hand side of an array destructuring assignment, is not an iterable object.
Iterable objects are a generalization of arrays. That's a concept that allows us to make any object useable in a for..of loop. Of course, Arrays are iterable.
To make an array iterable either you need to convert it to a stream or as a list using the asList() or stream() methods respectively. Then you can get an iterator for these objects using the iterator() method.
The Collection interface extends Iterable , so all subtypes of Collection also implement the Iterable interface.
Arrays can implement interfaces (Cloneable
and java.io.Serializable
). So why not Iterable
? I guess Iterable
forces adding an iterator
method, and arrays don't implement methods. char[]
doesn't even override toString
. Anyway, arrays of references should be considered less than ideal - use List
s. As dfa comments, Arrays.asList
will do the conversion for you, explicitly.
(Having said that, you can call clone
on arrays.)
The array is an Object, but its items might not be. The array might hold a primitive type like int, which Iterable can't cope with. At least that's what I reckon.
Arrays ought to support Iterable
, they just don't, for the same reason that .NET arrays don't support an interface that allows readonly random access by position (there is no such interface defined as standard). Basically, frameworks often have annoying little gaps in them, which it's not worth anyone's time to fix. It wouldn't matter if we could fix them ourselves in some optimal way, but often we can't.
UPDATE: To be even-handed, I mentioned .NET arrays not supporting an interface that supports random access by position (see also my comment). But in .NET 4.5 that exact interface has been defined and is supported by arrays and the List<T>
class:
IReadOnlyList<int> a = new[] {1, 2, 3, 4};
IReadOnlyList<int> b = new List<int> { 1, 2, 3, 4 };
All is still not quite perfect because the mutable list interface IList<T>
doesn't inherit IReadOnlyList<T>
:
IList<int> c = new List<int> { 1, 2, 3, 4 };
IReadOnlyList<int> d = c; // error
Maybe there is a possible backward compatibility gotcha with such a change.
If there's any progress on similar things in newer versions of Java, I'd be interested to know in the comments! :)
Unfortunately, arrays aren't 'class
-enough'. They don't implement the Iterable
interface.
While arrays are now objects that implement Clonable and Serializable, I believe an array isn't an object in the normal sense, and doesn't implement the interface.
The reason you can use them in for-each loops is because Sun added in some syntatic sugar for arrays (it's a special case).
Since arrays started out as 'almost objects' with Java 1, it would be far too drastic of a change to make them real objects in Java.
The compiler actually translates the for each
on an array into a simple for
loop with a counter variable.
Compiling the following
public void doArrayForEach() {
int[] ints = new int[5];
for(int i : ints) {
System.out.println(i);
}
}
and then decompiling the .class file yields
public void doArrayForEach() {
int[] ints = new int[5];
int[] var2 = ints;
int var3 = ints.length;
for(int var4 = 0; var4 < var3; ++var4) {
int i = var2[var4];
System.out.println(i);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With