while语句
while 语句是一种基本语句,目的是让 Java 执行重复的操作。换言之,while 语句是 Java的主要循环结构之一。句法如下:
while (expression)
statement
while 语句先计算 expression 的值,计算结果必须是布尔值。如果计算结果为 false,解释器跳过循环中的 statement,执行程序中的下一个语句。如果计算结果为 true,解释器执行组成循环主体的 statement,然后再次计算 expression 的值。如果计算结果为 false,解释器执行程序中的下一个语句;否则,再次执行 statement。只要 expression 的计算结果为 true,就会一直循环下去,while 语句结束后(即 expression 的计算结果为 false)解释器才会执行下一个语句。
下面是一个 while 循环示例,打印数字 0 到 9:
int count = 0;
while (count < 10) {
System.out.println(count);
count++;
}
可以看出,在这个示例中,变量 count 的起始值是 0,循环主体每执行一次,count 的值就会增加 1。循环执行 10 次后,表达式的计算结果变成 false(即 count 的值不再小于 10),此时 while 语句结束,Java 解释器继续执行程序中的下一个语句。大多数循环都有一个计数器变量,例如这个例子中的 count。循环计数器变量的名称经常使用 i、j 和 k,不过你应该使用意义更明确的名字,以便代码更易理解。
do-while语句
do-while 循环和 while 循环很像,不过循环表达式不在循环开头,而在循环末尾测试。也就是说,循环主体至少会执行一次。do-while 循环的句法如下:
do
statement
while (expression);
注意,do-while 循环和更普通的 while 循环有几个不同点。首先,do-while 循环既需要使用关键字 do标记循环的开头,也要使用关键字 while 标记循环的结尾,以及引入循环条件。其次,与while 循环不同的是,do-while 循环的结尾要使用分号。这是因为 do-while 循环以循环条件结尾,而不是标记循环主体结束的花括号。下面的 do-while 循环和前面的 while 循环打印相同的结果:
int count = 0;
do{
System.out.println(count);
count++;
}while(count < 10);
do-while 循环比类似的 while 循环少见得多,因为在实际使用中很少遇到一定会至少先执行一次循环的情况。
for语句
for 语句提供的循环结构往往比 while 和 do 循环更便利。for 语句利用了一般循环的执行模式。大多数循环都有一个计数器,或者某种形式的状态变量,在循环开始前初始化,然后测试这个变量的值,决定是否执行循环主体,再次计算表达式的值之前,在循环主体末尾递增或者以某种方式更新这个变量的值。初始化、测试和更新,这三步是循环变量的重要操作,for 语句把这三步作为循环句法的明确组成部分:
for ( initialize; test; update) {
statement
}
for 循环基本等同于下面的 while 循环:
initialize;
while (test) {
statement;
update;
}
把 initialize、test 和 update 三个表达式放在 for 循环的开头,特别有助于理解循环的作用,还能避免一些错误,例如忘记初始化或更新循环变量。解释器会丢掉 initialize和 update 两个表达式的返回值,所以它们必须有副作用。initialize 一般是赋值表达式,update 一般是递增、递减或其他赋值表达式。
下面的 for 循环与前面的 while 和 do-while 循环一样,打印数字 0 到 9:
int count;
for(count = 0 ; count < 10 ; count++)
System.out.println(count);
注意,这种句法把循环变量的重要信息都放在同一行,更能看清循环的执行方式。而且,把更新循环变量的表达式放在 for 语句中,还简化了循环主体,只剩一个语句,甚至不需要使用花括号组成语句块。
for 循环还支持一种句法,可以让循环更便于使用。很多循环都只在循环内部使用循环变量,因此 for 循环允许 initialize 是一个完整的变量声明表达式,这样循环变量的作用域是循环主体,在循环外部不可见。例如:
for(int count = 0 ; count < 10 ; count++)
System.out.println(count);
而且,for 循环的句法不限制只能使用一个变量,initialize 和 update 表达式都能使用逗号分隔多个初始化和更新表达式。例如:
for(int i = 0, j = 10 ; i < 10 ; i++, j--)
sum += i * j;
在目前所举的例子中,计数器都是数字,但 for 循环并不限制计数器只能使用数字。例如,可以使用 for 循环迭代链表中的元素:
for(Node n = listHead; n != null; n = n.nextNode())
process(n);
for 循环中的 initialize、test 和 update 表达式都是可选的,只有分隔这些表达式的分号是必须的。如果没有 test 表达式,其值假定为 true。因此,可以使用 for(;;) 编写一个无限循环。
遍历语句
Java 的 for 循环能很好地处理基本类型,但处理对象集合时没什么用,而且笨拙。不过,有种叫作“遍历循环”(foreach loop)的句法可以处理需要循环的对象集合。
遍历循环以关键字 for 开头,后面跟着一对括号,括号里是变量声明(不初始化)、冒号和表达式,括号后面是组成循环主体的语句(或语句块):
for( declaration : expression )
statement
别被遍历循环这个名字迷惑了,它并不使用关键字 foreach。冒号一般读作“......中”,例如“studentNames 中的各个名字”。
介绍 while、do-while 和 for 循环时,都举了一个例子,打印 10 个数字。遍历循环也能做到,但需要迭代一个集合。为了循环 10 次(打印 10 个数字),我们需要一个有 10 个元素的数组或其他集合。我们可以使用下面的代码:
// 这些是我们想打印的数字
int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
// 这是打印这些数字的循环
for(int n : primes)
System.out.println(n);
遍历for( declaration : expression )不能做的事
遍历和 while、for 或 do-while 循环不同,因为它隐藏了循环计数器或 Iterator 对象。介绍lambda 表达式时会看出来,这种想法很好,但有些算法不能使用遍历循环自然地表达出来。
假如你想把数组中的元素打印出来,各元素使用逗号分隔。为此,要在数组的每个元素后面打印一个逗号,但最后一个元素后面没有逗号;或者说,数组的每个元素前面都要打印一个逗号,但第一个元素前面没有逗号。使用传统的 for 循环,代码可以这样写:
for(int i = 0; i < words.length; i++) {
if (i > 0)
System.out.print(", ");
System.out.print(words[i]);
}
这是很简单的任务,但遍历做不到,因为遍历循环没有循环计数器,也没有其他能识别第一次、最后一次或中间某次迭代的方式。
使用遍历循环迭代集合中的元素也有类似的问题。使用遍历循环迭代数组时无法获取当前元素的索引,同样,使用遍历循环迭代集合也无法获取列举集合元素的 Iterator 对象。
还有一些事情遍历循环做不到:
1 反向迭代数组或 List 对象中的元素;
2 使用同一个循环计数器获取两个不同数组同一索引位的元素;
3 调用 List 对象的 get() 方法无法迭代其中的元素,必须调用 List 对象的迭代器。