foreach主要用于数组,但是它也可以应用于任何Collection对象。Collection可以和foreach一起工作是它Collection对象的一个特性。
之所以可以工作,是因为JavaSE5引入了一个新的被称为Iterable的接口,该接口包含了一个能够产生Iterator的Iiterator()方法,并且fIterable接口被foreach用来在序列中移动。因此如果你创建了任何实现Iterable的类,都可以将它用于foreach当中:
package practice;
import java.util.Iterator;
public class IterableClass implements Iterable<String> {
protected String[] word = ("And that is how"
+ "we know the Earthe to be banana-shaped.").split("");
@Override
public Iterator<String> iterator() {
return new Iterator<String>(){
private int index = 0;
@Override
public boolean hasNext() {
return index < word.length;
}
@Override
public String next() {
return word[index++];
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public static void main(String[] args) {
for (String string : new IterableClass()) {
System.out.print(string);
}
}
}
foreach语句可以用于数组和其他的Iterable,但是这并不意味着数组肯定也是一个Iterable,而任何自动包装也不会发生:
package practice;
import java.util.Arrays;
public class ArrayIsNotIterable {
static <T> void test(Iterable<T> ib){
for (T t : ib) {
System.out.print(t+" ");
}
}
public static void main(String[] args) {
test(Arrays.asList(1,2,3));
String[] strings={"A","B","C"};
//数组不鞥在foreach里工作,而且它不是Iterable;
//test(string);
//你必须手动执行转换
test(Arrays.asList(strings));
}
}
/**`output!
* 1 2 3 A B C
*/
适配器方法惯用法
如果有一个Iterable类,你想要加几种在foreach语句中使用这个类的方法,应该怎么做?如果直接继承这个类,并覆盖Iterator()方法,你只能替换现有的方法,而不能实现选择。
一种解决方案就是所谓的适配器。这里我们希望在foreach中向前迭代的基础上,添加反向迭代器的能力,因此我们不能使用覆盖,而是添加了一个能够产生ITerable对象的方法:
package practice;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
class ReversibleArrayList<T> extends ArrayList<T> {
/**
*
*/
private static final long serialVersionUID = 1L;
public ReversibleArrayList(Collection<T> c) {
super(c);
}
public Iterable<T> reversed() {
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
int current = size() - 1;
@Override
public boolean hasNext() {
return current > -1;
}
@Override
public T next() {
return get(current--);
}
@Override
public void remove() {
}
};
}
};
}
}
public class AdopterMethodIdiom {
public static void main(String[] args) {
ReversibleArrayList<String> ral = new ReversibleArrayList<>(Arrays.asList("To be or not to be".split(" ")));
for (String string : ral) {
System.out.print(string+" ");
}
System.out.println();
for (String string : ral.reversed()) {
System.out.print(string+" ");
}
}
}