Java 中的 for 循环

更新于 2025-12-25

Jakob Jenkov 发布于 2024-04-18

Java 的 for 循环用于重复执行一组 Java 操作。只要某个条件为真,for 循环就会不断重复执行一段代码块。下面是一个简单的 Java for 循环示例:

for(int i = 0; i < 10; i++) {
    System.out.println("i is: " + i);
}

这是一个标准的 Java for 循环。在 for 关键字后的括号 () 中,包含三个由分号 ; 分隔的语句。

  • 第一个语句声明了一个名为 iint 变量,并将其初始化为 0。该语句仅在 for 循环开始时执行一次。
  • 第二个语句将变量 i 的值与 10 进行比较。如果 i 小于 10,则再次执行 for 循环体。该语句在每次循环重复前都会被执行。
  • 第三个语句对 i 的值进行递增(i++)。该语句在每次循环体执行完毕后运行一次。

上述 for 循环的结果是:循环体共执行 10 次,分别对应 i09 的值。

实际上,你并不一定需要使用花括号 {} 包裹 for 循环体。如果你省略了花括号,则只有 for 循环语句之后的第一条 Java 语句会被视为循环体。例如:

for(int i = 0; i < 10; i++)
    System.out.println("i is 1: " + i); // 在循环内执行
System.out.println("second line");      // 在循环结束后执行

在这个例子中,只有第一个 System.out.println() 语句在 for 循环内部执行;第二个 System.out.println() 语句在 for 循环结束后才执行。

忘记为 for 循环体加上花括号是一个常见错误。因此,养成始终使用花括号包裹循环体的习惯是个好做法。


循环初始化器、条件和循环后操作

如前所述,for 循环括号内包含三个由分号分隔的语句。以下是前面示例中这三个语句的展示:

for(int i = 0; i < 10; i++) {
    System.out.println("I is: " + i);
}

这三个语句在 for 循环执行过程中扮演不同的角色:

  • 循环初始化器(Loop initializer)
  • 循环条件(Loop condition)
  • 循环后操作(Post iteration operation)

下面将逐一详细说明。

循环初始化器

循环初始化器语句只在 for 循环开始前执行一次。通常用于初始化循环条件中使用的变量或对象。例如,在以下代码中(加粗部分为初始化器):

for(int i = 0; i < 10; i++) {
    System.out.println("i is: " + i);
}

初始化器声明了一个 int 类型的变量 i 并赋初值为 0

注意:循环初始化器是可选的。以下是一个没有初始化器的 for 循环示例:

MyLoop loop = new MyLoop(10);
for( ; loop.loopAgain() ; loop.iterationDone()) {
}

这里使用一个对象来维护控制循环的状态。当然,这个对象也可以在初始化器中声明,此处只是为了说明可以省略初始化器。

你还可以在初始化器中同时声明多个变量,例如:

for(int i = 0, n = 10; i < n; i++) {
}

这里同时声明了两个变量:用作计数器的 i 和作为边界值的 n。注意,此时循环条件比较的是 in,而非常量。

条件

条件语句是 for 循环括号中的第二个语句。它是一个布尔表达式,结果必须为 truefalse。如果结果为 true,则继续执行下一次循环;如果为 false,则终止循环,并跳转到循环体之后的第一条语句。

例如,以下 for 循环中加粗的部分就是条件语句:

for(int i = 0; i < 10; i++) {
}

循环后操作

第三个语句是循环后操作(post iteration operation),在每次循环体执行完毕后运行。通常用于更新控制循环条件的变量,比如递增计数器。

例如:

for(int i = 0; i < 10; i++) {
}

这里的 i++ 就是循环后操作。它在每次循环结束后将 i 增加 1,而条件语句会检查 i 是否仍小于 10

注意:循环后操作也是可选的。例如:

MyLoop loop = new MyLoop(10);
for( ; loop.loopAgain(); ) {
}

Java 的 for-each 循环

从 Java 5 开始,引入了一种 for 循环的变体,称为 for-each 循环。示例如下:

String[] strings = {"one", "two", "three"};
for(String aString : strings) {
    System.out.println(aString);
}

注意这里的 String 数组 strings。在 for-each 循环中,括号内声明了一个 String 类型的变量 aString。在每次迭代中,该变量会依次绑定到数组中的每个元素。循环次数等于数组的长度。

for-each 循环也可用于泛型集合。


continue 命令

Java 提供了 continue 命令,可用于 for(以及 while)循环内部。当程序执行到 continue 时,JVM 会立即跳过当前循环体的剩余部分,直接进入下一次迭代。

注意:即使执行了 continue,当前迭代的“循环后操作”仍然会执行。

示例:

String[] strings = { "John", "Jack", "Abraham", "Jennifer", "Ann" };
int wordsStartingWithJ = 0;
for(int i = 0; i < strings.length; i++) {
    if(! strings[i].toLowerCase().startsWith("j")) {
        continue;
    }
    wordsStartingWithJ++;
}

此例中,若字符串不以字母 j 开头,则跳过后续代码,直接进入下一次循环;否则,计数器 wordsStartingWithJ 加 1。

continue 同样适用于 for-each 循环:

String[] strings = { "John", "Jack", "Abraham", "Jennifer", "Ann" };
int wordsStartingWithJ = 0;
for(String aString : strings) {
    if(! aString.toLowerCase().startsWith("j")) {
        continue;
    }
    wordsStartingWithJ++;
}

逻辑完全相同,只是语法略有不同。


break 命令

break 命令也可在 for(及 while)循环中使用。一旦执行 break,JVM 会立即退出整个循环,即使循环条件仍为真,也不会再执行后续迭代。

示例:

String[] strings = { "John", "Jack", "Abraham", "Jennifer", "Ann" };
int wordsStartingWithJ = 0;
for(int i = 0; i < strings.length; i++) {
    if(strings[i].toLowerCase().startsWith("j")) {
        wordsStartingWithJ++;
    }
    if(wordsStartingWithJ >= 3) {
        break;
    }
}

当找到第 3 个以 j 开头的单词时,break 被触发,循环立即终止。

同样,break 也适用于 for-each 循环:

String[] strings = { "John", "Jack", "Abraham", "Jennifer", "Ann" };
int wordsStartingWithJ = 0;
for(String aString : strings) {
    if(aString.toLowerCase().startsWith("j")) {
        wordsStartingWithJ++;
    }
    if(wordsStartingWithJ >= 3) {
        break;
    }
}

Java for 循环中的变量可见性

for 循环的括号或循环体内声明的变量,其作用域仅限于该循环体内。这一点对 for-each 循环同样适用。

例如:

for(int i = 0; i < 10; i++) {
    String iAsNo = String.valueOf(i);
}

变量 iiAsNo 只能在循环体内访问,循环外部无法引用它们。

同样,在 for-each 循环中:

String[] strings = {"one", "two", "three"};
for(String aString : strings) {
    System.out.println(aString);
}

由于 aString 是在 for-each 循环括号内声明的,因此它只能在循环体内使用。