while、do-while 和 for 用来控制循环,它们也叫作迭代语句(iteration statement)。迭代语句会重复执行,直到起控制作用的布尔表达式结果变为 false。while 循环的格式如下:

  1. while(Boolean-expression)
  2. statement

在循环刚开始时会计算一次布尔表达式的值,而在下一次迭代之前会再计算一次。
下面的例子会一直生成随机数,直到满足特定条件为止:

  1. // control/WhileTest.java
  2. // 演示while循环
  3. public class WhileTest {
  4. static boolean condition() {
  5. boolean result = Math.random() < 0.99;
  6. System.out.print(result + ", ");
  7. return result;
  8. }
  9. public static void main(String[] args) {
  10. while(condition())
  11. System.out.println("Inside 'while'");
  12. System.out.println("Exited 'while'");
  13. }
  14. }
  15. /* 输出(最开始和最后的5行):
  16. true, Inside 'while'
  17. true, Inside 'while'
  18. true, Inside 'while'
  19. true, Inside 'while'
  20. true, Inside 'while'
  21. ...________...________...________...________...
  22. true, Inside 'while'
  23. true, Inside 'while'
  24. true, Inside 'while'
  25. true, Inside 'while'
  26. false, Exited 'while'
  27. */

condition() 方法使用了 Math 库里的静态方法 random()。该方法会生成一个范围为 0~1(包括0,但不包括1)的 double 值。返回的结果是一个布尔值,通过比较操作符<产生。while条件表达式的意思是“重复执行循环里的主体语句,直到 condition() 方法返回 false ”。

5.3.1 do-while

do-while 语句的格式如下:

  1. do
  2. statement
  3. while(Boolean-expression);

while 和 do-while 的唯一的区别是 do-while 中的语句至少会执行一次,即便表达式的第一次计算结果就是false。而在 while 中,如果条件表达式第一次得出的值就是 false,则它的语句根本不会执行。在日常使用中,while 要比 do-while 更常用一些。

5.3.2 for

for 循环可能是最常用的迭代形式,这种循环在第一次迭代前会先进行初始化,然后再进行条件测试。在每次迭代结束后,还会有某些形式的“步进”。for 循环的格式如下:

  1. for(initialization; Boolean-expression; step)
  2. statement

上面的初始化表达式(initialization)、布尔表达式(Boolean-expression)和步进(step)都可以为空。每次迭代前会测试布尔表达式。只要结果是 false,就不再循环,而是执行跟在 for 循环后面的语句。每次循环结束,都会执行一次步进。
for 循环常用于执行 “计数” 任务:

  1. // control/ListCharacters.java
  2. // 展示所有的小写ASCII字母
  3. public class ListCharacters {
  4. public static void main(String[] args) {
  5. for(char c = 0; c < 128; c++)
  6. if(Character.isLowerCase(c))
  7. System.out.println("value: " + (int)c +
  8. " character: " + c);
  9. }
  10. }
  11. /* 输出(前10行):
  12. value: 97 character: a
  13. value: 98 character: b
  14. value: 99 character: c
  15. value: 100 character: d
  16. value: 101 character: e
  17. value: 102 character: f
  18. value: 103 character: g
  19. value: 104 character: h
  20. value: 105 character: i
  21. value: 106 character: j
  22. ...
  23. */

注意变量 c 是在使用时被定义的,它发生在 for 循环的控制表达式里,而不是在 main() 方法开始的地方。 c 的作用域就是 for 循环控制的语句范围内。
像 C 这种传统的过程式语言要求所有变量都在程序开始的地方定义。当编译器创建它们的时候,会为这些变量分配空间。而在 Java 和C++中,你可以把变量声明分散在整个程序里,在真正需要的时候才定义。这样的编程风格更自然,也更易于理解。1

1在早期的语言中,设计者所做的大量决定是为了让编译器开发者的工作更轻松。而在现代语言中,大多数设计决策是为了让编程语言的使用者工作更轻松,尽管有时会有妥协——这一般最终会成为语言设计者的遗憾。

上面的程序使用了 java.lang.Character 包装器类,它不仅可以把char基本类型的值包装进对象,还提供了其他一些有用的工具。这里用到的静态方法 isLowerCase() 可以检测出相关字符是否为小写字母。

5.3.3 逗号操作符

逗号操作符不是逗号分隔符,逗号分隔符用来分隔声明和函数的不同参数,而 Java 里唯一用到逗号操作符的地方就是 for 循环的控制表达式。在控制表达式的初始化和步进部分,都可以使用一系列由逗号分隔的语句,而这些语句会按先后顺序执行。
通过使用逗号操作符,你可以在 for 语句里定义多个变量,但它们必须是相同的类型。

  1. // control/CommaOperator.java
  2. public class CommaOperator {
  3. public static void main(String[] args) {
  4. for(int i = 1, j = i + 10; i < 5; i++, j = i * 2) {
  5. System.out.println("i = " + i + " j = " + j);
  6. }
  7. }
  8. }
  9. /* 输出:
  10. i = 1 j = 11
  11. i = 2 j = 4
  12. i = 3 j = 6
  13. i = 4 j = 8
  14. */

以上 for 语句里的 int 参数定义包括 i 和 j,在初始化部分可以定义同一个类型的任意数量的变量。在控制表达式里定义多个变量的能力只限于 for 循环,在其他任何选择或迭代语句中都不能使用这种方式。
在初始化和步进部分,语句都是按先后顺序执行的。