好好学Java:从零基础到项目实战
上QQ阅读APP看书,第一时间看更新

3.2.3 while循环

循环是流程控制的又一重要结构,“白天-黑夜-白天-黑夜”属于时间上的循环,古人“年复一年、日复一日”的“日出而作、日落而息”便是每天周而复始的生活。计算机程序处理循环结构时,给定一段每次都要执行的代码块,然后分别指定循环的开始条件和结束条件,就形成了常见的循环语句。最简单的循环结构只需一个while关键字设置循环条件即可。下面是根据输入数字决定循环次数的代码例子(完整代码见本章源码的src\com\control\process\WhileLoop.java):

        System.out.println("长夜漫漫,无心睡眠,请给他设定一个睡醒的年限");
        Scanner scan=new Scanner(System.in);  // 从控制台接收输入文本
        int limit=scan.nextInt();  // nextInt方法表示接收一个整数,以回车键结尾
        int year=0;
        while (year < limit) {  // 当条件满足时,在循环内部持续处理
            System.out.println("已经过去的年份:"+year);
            year++;
        }
        System.out.println("他足足睡了这么多年:"+year);

运行上面的测试代码,输入数字3,连同处理结果的完整日志如下:

长夜漫漫,无心睡眠,请给他设定一个睡醒的年限

3

已经过去的年份:0

已经过去的年份:1

已经过去的年份:2

他足足睡了这么多年:3

单纯的while语句是在每次循环开始前判断条件,符合条件就执行一遍代码,不符合的话就退出循环。Java还提供了另一种形式的do-while循环,该循环以do关键字开头,以while语句结尾,并且条件判断挪到了每次循环结束后再处理。条件判断的位置变更造成了while循环和do-while循环之间的差异:while循环在开始工作前必定先判断循环条件是否成立,一旦条件不成立,那么当前循环一次都不会执行,直接跳到循环后面的语句;而do-while循环直至第一次循环执行完毕才做条件判断,只有发现循环条件不成立时才姗姗来迟退出循环。这意味着,即使循环条件一开始就不满足,do-while循环也一定要进入循环内部,到此一游后才拍拍屁股离开。

下面通过一个实验观察while循环和do-while循环的不同之处,演示代码如下,主要是把循环外围的while改成do-while(完整代码见本章源码的src\com\control\process\WhileLoop2.java):

        int year=0;
        do {  // 开始循环处理
            System.out.println("已经过去的年份:"+year);
            year++;
        } while (year < limit);  // 当条件满足时,在循环内部持续处理
        System.out.println("他足足睡了这么多年:"+year);

然后运行演示代码,倘若输入正数,则while循环和do-while循环打印的日志信息并无区别;要是输入负数,二者打印的日志就分道扬镳了。假设两种循环情况下都输入-1,则while循环的日志打印结果如下:

长夜漫漫,无心睡眠,请给他设定一个睡醒的年限

-1

他足足睡了这么多年:0

而do-while循环的日志打印结果如下:

长夜漫漫,无心睡眠,请给他设定一个睡醒的年限

-1

已经过去的年份:0

他足足睡了这么多年:1

从上面的实验结果看出,在条件不满足的情况下,do-while循环依旧强行蹓跶了一圈,这种先斩后奏的特性过于武断,故而限制了它的使用范围。

无论是while循环还是do-while循环,它们的条件判断都独立于循环内部代码,要么在循环开始前判断,要么在循环结束后判断。如果要求在内部代码的中间就插入条件判断,并据此决定是退出循环还是继续循环,该如何实现呢?为此Java给循环语句引入了break和continue两个关键字,其中break的作用是跳出整个循环,而continue的作用是跳过本次循环的剩余代码,继续下次的循环判断和处理。

现在准备修改之前的代码,打算在println和year++中间判断是否继续循环。首先要把while语句后面的条件式子改为true,表示每次循环前后取消默认的条件校验。然后在println和year++之间插入if语句判断条件,条件满足的话,就执行year++和continue操作;条件不满足的话,就直接跳出整个循环,继续循环以外的代码处理。根据上述思路修改循环代码,改好的代码如下(完整代码见本章源码的src\com\control\process\WhileLoop3.java):

        int year=0;
        while (true) {  // 当条件满足时,在循环内部持续处理
            System.out.println("已经过去的年份:"+year);
            if (year < limit) {  // 这里判断能否跳出循环
                year++;
                continue;  // 继续下一次循环
            } else {
                break;  // 跳出循环,即跳到while循环的右花括号之后
            }
        }
        System.out.println("他足足睡了这么多年:"+year);

接着运行修改之后的代码,打印出来的循环运行日志如下:

长夜漫漫,无心睡眠,请给他设定一个睡醒的年限

3

已经过去的年份:0

已经过去的年份:1

已经过去的年份:2

已经过去的年份:3

他足足睡了这么多年:3

可见此时循环内部接连打印了年份0、年份1、年份2、年份3,共4行日志。对比修改之前只打印年份0、年份1、年份2的3行日志,显然修改之后的代码逻辑更灵活,因为无论循环的内部代码如何千变万化,程序总能找到合适的地方退出循环处理。