Iterable<E>
is in java.lang
whereas Iterator<E>
is in java.util
. Is there a good reason for this or is this merely an artifact of bad design?
It seems strange since the only thing that an Iterable<E>
is good for is providing an Iterator<E>
.
EDIT: One potential reason is because of the (then-)newly introduced for-each loop. I guess my question then would be, are they equivalent?
for(Object o : collection)
...
vs
for( Iterator iter = collection.iterator(); iter.hasNext(); ) {
o = iter.next();
...
If they are, then that still doesn't explain why the two classes are in different packages since the compiler would have to import java.util
anyways to use the Iterator
construc开发者_运维知识库t.
Part of it is history: Iterator
has been with us since JDK 1.2, and Iterable
came with JDK 1.5. Iterable
came in with the enhanced for
loop.
Bad design? No, evolution. There's no all-knowing creator. As lessons are learned they're incorporated into the JDK.
java.lang
is reserved for classes which are dependencies for language features. Iterable
has language level support directly via the for-each loop but Iterator
does not.
Most of the collections implement Iterable
so that you can use the convenient for loop syntax:
Iterable<T> someIterableThing;
for (T x : someIterableThing) { ... }
I would imagine that Iterable
is in java.lang
because it's strongly related to this syntax, a feature of the Java language.
Over time, Java's java.*
subpackages have developed various circular dependencies. For example,
- java.lang.Process -- java.io
- java.lang.Readable -- java.io, java.nio
- java.lang.String -- java.util
- java.lang.System -- java.io, java.nio, java.util
So I think it is best to not think about subpackages as a mechanism to clearly layer dependencies. Rather, the subpackages group related, specialized behavior (except for the catch-all util
), and lang
selectively pulls in some very useful constructs like Iterator
and Locale
.
I guess one could also chalk it all up to entropy.
To answer the additional question:
The enhanced for loop has two variants. One of them, when the collection
argument in
for(E o : collection) {
...
}
is something which implements Iterable<E>
, is exactly equivalent to
for (Iterator<E> iter = collection.iterator(); iter.hasNext(); ) {
E o = iter.next();
...
}
(with the difference that the Iterator has no variable name that you can access in the rest of the loop). The compiler will generate quite similar or even exactly the same code for each version.
There is another variant of the enhanced for
loop: when the collection
is an array, it will get compiled to something like this:
E[] a = collection;
for(int i = 0; i < a.length; i++) {
E o = a[i];
...
}
(Of course, here we can't directly access a
or i
, too.)
By the way, the compiler does not import java.util.Iterator
- in the compiled bytecode, each type is referred to by its full name. (And local variables are not really typed, anyway - other for some checkcast
assertions.)
精彩评论