考虑:

List<String> someList = new ArrayList<String>();
// add "monkey", "donkey", "skeleton key" to someList
for (String item : someList) {
    System.out.println(item);
}

如果不使用for each语法,等价的for循环会是什么样子?


当前回答

正如许多好答案所说,如果一个对象想要使用for each循环,它必须实现Iterable接口。

我将发布一个简单的示例,并尝试以不同的方式解释for each循环的工作原理。

对于每个循环示例:

public class ForEachTest {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();
        list.add("111");
        list.add("222");

        for (String str : list) {
            System.out.println(str);
        }
    }
}

然后,如果我们使用javap来反编译这个类,我们将得到这个字节码示例:

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: new           #16                 // class java/util/ArrayList
         3: dup
         4: invokespecial #18                 // Method java/util/ArrayList."<init>":()V
         7: astore_1
         8: aload_1
         9: ldc           #19                 // String 111
        11: invokeinterface #21,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        16: pop
        17: aload_1
        18: ldc           #27                 // String 222
        20: invokeinterface #21,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        25: pop
        26: aload_1
        27: invokeinterface #29,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;

从示例的最后一行可以看到,编译器将在编译时自动将for每个关键字的使用转换为Iterator的使用。这可以解释为什么对象(它没有实现Iterable接口)在尝试使用for each循环时会抛出异常。

其他回答

for (Iterator<String> i = someIterable.iterator(); i.hasNext();) {
    String item = i.next();
    System.out.println(item);
}

注意,如果需要使用i.remove();在循环中,或者以某种方式访问实际的迭代器,不能使用for(:)习惯用法,因为实际的迭代器只是推断出来的。

正如Denis Bueno所指出的,这段代码适用于实现Iterable接口的任何对象。

此外,如果for(:)习惯用法的右侧是数组而不是Iterable对象,则内部代码使用int索引计数器并检查array.length。请参阅Java语言规范。

使用forEach:

int[] numbers = {1,2,3,4,5};

Arrays.stream(numbers).forEach(System.out::println);

答复:

1
2
3
4
5

The process finished with exit code 0

PS:您需要一个Array(int[]数字),然后导入java.util.Arrays;

这里有一个答案,它不假定了解Java迭代器。它不太精确,但对教育有用。

在编程时,我们通常编写如下代码:

char[] grades = ....
for(int i = 0; i < grades.length; i++) {   // for i goes from 0 to grades.length
    System.out.print(grades[i]);           // Print grades[i]
}

foreach语法允许以更自然、更少语法噪音的方式编写这种常见模式。

for(char grade : grades) {   // foreach grade in grades
    System.out.print(grade); // print that grade
}

此外,此语法对于不支持数组索引但实现Java Iterable接口的Lists或Set等对象有效。

for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}

forEach的替代方案,以避免“for each”:

List<String> someList = new ArrayList<String>();

变体1(普通):

someList.stream().forEach(listItem -> {
    System.out.println(listItem);
});

变体2(并行执行(更快)):

someList.parallelStream().forEach(listItem -> {
    System.out.println(listItem);
});