Java宝典
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

第3章 流程控制

本章包括

◆ 分支控制语句的使用

◆ 跳转控制语句的使用

◆ 循环控制语句的使用

◆ 利用流程控制解决实际问题

Java的流程控制语句是程序设计的基础,在程序的设计中需要经常用到。Java的流程控制语句主要包括分支控制、循环控制、跳转控制以及例外控制(异常处理)4种。本章主要介绍前3种流程控制语句,例外控制将在第14章中进行讲解。

3.1 分支控制语句

分支控制语句包括条件结构的if…else和多分支选择的switch。if语句共有3种形式,包括简单的if语句、if…else语句以及嵌套的if…else语句。分支控制语句通过判断条件表达式是true还是false来决定程序的执行。switch语句是一个可以用于多分支选择的语句。本节主要介绍if…else语句和switch语句的用法。

3.1.1 简单的if语句

if语句是Java语言中的一种分支控制语句,它通过判断给定条件的值是true还是false来决定下一步的执行情况。它可以包括多种形式,其中简单的if语句的基本格式如下:

      if (表达式){
              语句1;
              语句2;
              ……
      }

在这个if语句中,表达式是逻辑表达式或者关系表达式。如果表达式的结果为true,就会执行花括号后面的语句,该语句可以有一个,也可以有多个。简单的if语句的执行流程如图3-1所示。

图3-1 简单if语句流程图

如果在if表达式后,只有一个语句,可以不使用花括号将其括起来,例如:

        if (sum %2>0)   sum = sum+1;          //如果和是奇数,则让该值加1

如果在if表达式后,有两个或者两个以上的语句,就必须使用花括号将其括起来,同时要注意代码的缩进,例如:

        if (sum %2>0){                         //判断和是否为奇数
                sum = sum+1;                   //总数加1
                average = sum/20;              //计算平均值
        }

在实际应用中,尽量使用花括号将需要在if表达式里执行的语句括起来,即使只有一个语句,也建议使用花括号,这样有利于增强程序的可读性。

3.1.2 if…else语句基本格式

可以在if语句之后添加一个else语句,如果判断给定条件的值是true,就执行if后面的语句,如果判断给定条件的值是false,就执行else后面的语句。if…else语句的基本格式如下:

      if (表达式){
              语句1;
              ……
      }else{
              语句2;
              ……
      }

该语句的执行流程如图3-2所示。

图3-2 if…else语句流程图

下面来看一个字母转换的例子。输入一个字符,如果是小写字母,将其转换为大写字母,否则不转换。对于这个问题,首先要了解字符的大小写之间是如何转换的。在ASCII码中,大写的字母A对应的值是65,小写的字母a对应的值是97,它们之间差了32。其他字母的大小写也是这样,ASCII码对应的值都相差32。所以让一个小写字母转换成大写字母,只要将得到的ASCII码对应的值减去32即可。因此实现字母转换的代码如下:

        import java.io.*;
        public class CharConvert{
            public static void main(String args[]) throws IOException{
                /*读取从键盘上输入的字符*/
                InputStreamReader reader = new InputStreamReader(System.in);
                BufferedReader bf = new BufferedReader(reader); //创建字符输入流对象
                System.out.print("put:" );                    //在键盘上输入字符
                String s = bf.readLine();                     //读取从键盘上输入的字符
                char c = s.charAt(0);                      //取得字符串中第一个字符的值
                if(c>=' a' &&c<=' z' ){
                    /*当字母是小写字母时,将其转换为大写*/
                    c = (char)(c-32);                      //将小写字母转换为大写字母
                    System.out.println("对应的大写字母为:"+c);   //打印输出对应的大写字母
                }else{
                    /*如果是大写字母,就原样输出 */
                    System.out.println(c);                     //打印输出大写字母
                }
            }
        }

上面的代码首先使用import引入了java.io包,因为在方法中要抛出一个IOException异常。其中前5句是读取从键盘上输入的字符串。抛出异常和字符流的内容将在第14章和第19章中讲解,这里读者只要知道通过这5句可以读取到键盘上输入的字符就可以了。然后使用字符串中的charAt()方法读取该字符串中的第一个字符,判断该字符是大写字母还是小写字母,如果是小写字母,将其值减去32转变成大写字母,如果字符是大写的,就将其原样输出,其运行结果如图3-3所示。

图3-3 字符转换的运行结果

在第2章中讲过一个条件运算符,有些时候用它可以简化代码的编写。例如,上面的这个例子用条件运算符可以这样来完成。

        c = (c>=' a' &&c<=' z' )? (char)(c-32):c;
        //当字母是小写字母时,将其转换为大写,否则原样输出

如果有多种条件,可以使用下面的形式。

      if (表达式){
              语句1;
              ……
      }else if{
              语句2;
              ……
      }else if{
              语句3;
              ……
      }else{
              语句4;
      }

例如上一个例子中,改成如果是小写字母,将其转换为大写字母,如果是大写字母,将其转换为小写字母,否则输出“这不是一个字母”。可以使用下面的代码来完成。

        if(c>=' a' &&c<=' z' ){                        //当字母是小写字母时,将其转换为大写字母
                c = (char)(c-32);                  //将小写字母转换为大写字母
                System.out.println("对应的大写字母为:"+c);   //打印输出对应的大写字母
        }else if(c>=' A' &&c<=' Z' ){                //如果是大写字母,将其转换为小写字母
                c = (char)(c+32);                  //将大写字母转换为小写字母
                System.out.println("对应的大写字母为:"+c);   //打印输出对应的小写字母
        } else{                                   //如果不是字母
                System.out.println("这不是一个字母"); //打印输出不是字母的信息
        }

这里是使用if…else多种条件判断来实现字母的大小写转换的。首先判断输入的字符是不是小写字母,如果是则将其转换为大写字母,如果不是再判断输入的字符是不是大写字母,如果是则将其转换为小写字母。如果输入的字符既不是一个大写字母也不是一个小写字母,就打印输出“这不是一个字母”提示信息。在本书光盘“源文件\03\3.1\3.1.2”中有该段程序的源代码(CharConvert2.java),读者可以自己编译运行看一下其运行结果。

3.1.3 嵌套的if…else语句

if…else语句是可以嵌套使用的,即在一个if…else语句中可以嵌套一个或者几个if…else语句。使用if…else语句的嵌套可以实现一个比较复杂的逻辑关系。嵌套的if…else语句格式如下:

      if (表达式1){
          if (表达式2){
              语句1;
              ……
          }else{
              语句2;
              ……
          }
      }else{
          if (表达式3){
              语句3;
              ……
          }else{
              语句4;
              ……
          }
      }

在嵌套的if…else语句中,else一定是和最近的那个if语句进行匹配的,而且在程序中else不能单独出现。上述嵌套if…else语句的意思是:如果表达式1的结果为true,则会判断表达式2的结果,如果表达式2的结果为true,则执行语句1,如果表达式2的结果为false,则执行语句2;如果表达式1的结果为false,则会判断表达式3的结果;如果表达式3的结果为true,则执行语句3;如果表达式3的结果为false,则执行语句4。其语句的执行流程如图3-4所示。

图3-4 嵌套if…else语句流程图

在使用嵌套的if…else语句时,为了保证在语句的嵌套过程中不出现错误,应该尽量使用代码的缩进,同时也有利于增强程序的可读性。

3.1.4 switch多分支选择语句

switch语句是个多分支的选择语句,它可以根据表达式产生的不同结果值选择执行的下一个语句,这里表达式的类型只能是char, byte, short或者int。它的语法格式如下:

            switch (表达式){
            case value1:
                语句1;
                break;
            case value2:
          语句2;
          break;
          ……
      default:
          语句;
      }

该语句的意思是对于一个给定的表达式,如果它的值为value1,就执行value1后面的语句1,如果它的值为value2,就执行value2后面的语句2,如果没有任何一个值与给定的表达式的值相等,就执行default后面的语句。其流程图如图3-5所示。

图3-5 switch语句流程图

从流程图可以看出,如果不写break,程序会继续执行下一个case value所对应的语句。下面来看一个例子。在键盘上输入0~6的整数,来代表一周的7天。完成一个程序,分别用中、英、日3种文字输出整数代表的是一周中的哪一天。这个程序用switch语句完成的代码如下:

        import java.io.*;
        /*取得0~6的整数所表示的星期数*/
        public class WeekTest{
            public static void main(String args[]) throws IOException{
                /*读取从键盘上输入的字符*/
                InputStreamReader reader = new InputStreamReader(System.in);
                BufferedReader bf = new BufferedReader(reader); //创建字符输入流对象
                System.out.print("put the number of 0-6:" );   //在键盘上输入字符
                String s = bf.readLine();                     //读取从键盘上输入的字符
                int a = Integer.parseInt(s);           //将从键盘上取得的值转换为整数
                /*根据取得的键盘的输入值,打印输出不同的信息*/
                switch(a){
                    case 0:                            //如果键盘中输入的值是0
                  System.out.println("今天是星期一"); //打印输出星期一对应的中文表达
                  System.out.println("Today is Monday");
                                                  //打印输出星期一对应的英文表达
                  System.out.println("今日は月曜日です");
                                                  //打印输出星期一对应的日文表达
                  break;                         //退出switch语句
              case 1:                            //如果键盘中输入的值是1
                  System.out.println("今天是星期二");  //打印输出星期二对应的中文表达
                  System.out.println("Today is Tuesday ");
                                                  //打印输出星期二对应的英文表达
                  System.out.println("今日は火曜日");  //打印输出星期二对应的日文表达
                  break;                         //退出switch语句
              case 2:                            //如果键盘中输入的值是2
                  System.out.println("今天是星期三");  //打印输出星期三对应的中文表达
                  System.out.println("Today is Wednesday");
                                                  //打印输出星期三对应的英文表达
                  System.out.println("今日は水曜日");  //打印输出星期三对应的日文表达
                  break;                         //退出switch语句
              case 3:                            //如果键盘中输入的值是3
                  System.out.println("今天是星期四");  //打印输出星期四对应的中文表达
                  System.out.println("Today is Thursday");
                                                  //打印输出星期四对应的英文表达
                  System.out.println("今日は木曜日です");
                                                  //打印输出星期四对应的日文表达
                  break;                         //退出switch语句
              case 4:                            //如果键盘中输入的值是4
                  System.out.println("今天是星期五");  //打印输出星期五对应的中文表达
                  System.out.println("Today is Friday");
                                                  //打印输出星期五对应的英文表达
                  System.out.println("今日は金曜日です");
                                                  //打印输出星期五对应的日文表达
                  break;                         //退出switch语句
              case 5:                            //如果键盘中输入的值是5
                  System.out.println("今天是星期六");  //打印输出星期六对应的中文表达
                  System.out.println("Today is Saturday");
                                                  //打印输出星期六对应的英文表达
                  System.out.println("今日は土曜日");  //打印输出星期六对应的日文表达
                  break;                         //退出switch语句
              case 6:                            //如果键盘中输入的值是6
                  System.out.println("今天是星期日");  //打印输出星期日对应的中文表达
                  System.out.println("Today is Sunday");
                                                  //打印输出星期日对应的英文表达
                  System.out.println("今日は日曜日です");
                                                  //打印输出星期日对应的日文表达
                  break;                         //退出switch语句
              default:                   //如果键盘中输入的值不是0~6中的某一个数
                  System.out.println("数据输入错误");  //打印输出数据输入错误信息
          }
      }
  }

首先还是要使用import引入java.io包,读取从键盘中输入的字符串。然后使用Integer类中的parseInt()方法将读取到的字符串转换成整型,并使用switch语句对其值进行判断,如果输入的值是0~6之间的数,则以中文、英文和日文3种文字打印输出其数字相对应星期数,如果输入的是其他值,则将default关键字后面的错误信息打印输出。其运行结果如图3-6所示。

图3-6 switch代码运行结果

读者可以把其中的某一个或几个break去掉,然后将该程序再编译运行一次,看一下运行结果有什么变化。

在使用switch语句的时候,需要注意以下几点。

◆ 表达式中只能有一个值,只能与常量进行比较,类型也只能是char, byte, short或者int类型。

◆ 每一个case对应的value都是唯一的,case value的值不能重复。

◆ default关键字在switch语句中只能出现一次,也可以不使用default关键字。

◆ 在每一个case中,都需要用一个break来终止switch语句。

3.2 循环控制语句

如果现在需要计算1+2+3+…+10的累加和,使用顺序结构需要对相同的语句计算多次才能得到最后的结果。如果计算累加和的语句能在给定的条件下重复执行多次,那问题就会变得简单了,这就需要使用Java语言中的循环控制语句。Java语言中的循环控制语句主要包括while, do…while和for循环。其中for循环包括普通的for循环和for/in循环(或者叫for each循环)。这一节将主要介绍while, do…while和普通for循环的用法。for/in循环是Java 5.0新增加的一种循环方式,也被称为增强的for循环,将在第4章中介绍。

3.2.1 while循环语句

在程序设计中,有时需要根据给定的逻辑表达式的结果是true还是false,来决定是否需要重复执行循环体中的语句,这时就需要使用while循环语句。while循环语句的基本格式如下:

      while (条件表达式){
              循环语句;
              ……
      }

该语句的意思是当条件表达式的结果为true时,可以反复执行循环体中的语句,直到条件表达式的结果为false时才会退出循环。如果条件表达式的初始结果为false,则while循环体中的语句一次也不会被执行。其流程图如图3-7所示。

图3-7 while循环流程图

下面来看一个例子,计算1+2+22+23+…+210的值。

        public class SumTest{
            public static void main(String args[]){
                int sum = 1;                   //设置sum的初始值为1
                int a = 1;                     //设置a的初始值为1
                int n = 1;                     //设置n的初始值为1
                while(n<=10){                  //循环10次
                    a = a*2;                   //计算2的n次方的值
                    sum = sum+a;               //计算最后的累加和
                    n= n+1;                    //变量n加1,进行下一次循环
                }
                System.out.println("sum = "+sum);  //打印输出计算后累加和的值
            }
        }

这段代码使用while语句来计算1+2+22+23+…+210的值。在while循环中,首先计算2的n次方的值,将得到的结果相加并赋给变量sum,然后将n的值加1,进行下一次的循环。例如,当n=1时,先计算a*2的值并将结果赋给变量a,此时a的值为2,再将该值与sum的值相加并将结果赋给sum,即sum的值为3(1+2),然后将n的值加1,此时n=2。由于2小于10,所以继续执行第二次循环,再计算a*2的值,此时a的值变为4(2*2)。再将该值与sum的值相加并将结果赋给sum,此时sum的值为7(3+4),然后n的值再加1,依此类推,直到n的值大于10退出循环为止。其运行结果为:

        sum = 2047

while还可以嵌套使用,其格式如下:

      while (表达式){
              //程序代码
              while {表达式}{
                  //程序代码
              }
      }

在使用while语句时,如果while语句的表达式始终为true,就可能会产生死循环,所以在使用中要注意对循环条件的控制,在while循环中要有能够控制循环条件的语句。

3.2.2 do…while语句

在while循环语句中,如果条件表达式的初始结果为false,则while循环体中的语句一次也不会被执行。但是有时却希望能够至少执行一次while循环体中的语句,这时就可以使用do…while语句。do…while语句的基本格式如下:

        do
        {
        语句;
        ……
        }while (条件表达式);

该语句会首先执行一次循环体,然后再判断条件表达式的结果是否为true。它和while语句的区别在于,不管表达式的条件是否成立,都会先执行一次循环体中的语句。其流程图如图3-8所示。

图3-8 do…while流程图

可以将3.2.1中的例子用do…while语句来完成,方法如下:

        do{
                a = a*2;                   //计算2的n次方的值
                sum = sum+a;               //计算加和
                n= n+1;                    //变量n加1,进行下一次循环
            }while(n<=10);                 //循环10次

do…while语句也可以嵌套使用,其格式如下:

        do{
            //程序代码
            do{
                //程序代码
            }while (表达式);
      }while (表达式);

当然它也可以和while语句进行嵌套,其格式如下:

      while (表达式){
          //程序代码
          do{
              //程序代码
          }while (表达式);
      }

3.2.3 for循环语句

在有些情况下,循环的次数是可以预知的。例如,计算1+2+3+…+10的值,这里很明显需要循环10次,像这样可以明确地知道循环次数的问题,就可以使用for循环语句来完成。for循环语句的基本格式如下:

      for (初始条件;表达式;步长){
          循环语句;
          ……
      }

该语句的判断条件共分为3个部分。初始条件用来给定初始值。表达式作为循环的条件,一般为关系表达式或者逻辑表达式,只有在其值为true的情况下,才执行循环体里面的语句,如果其值是false的话,则会跳出循环体,执行循环体以后的语句。步长相当于一个计数器,既可以进行累加,也可以进行递减操作。其流程图如图3-9所示。

图3-9 for循环流程图

从这个流程图可以看出,如果表达式的结果为true,它就会执行循环体的内容。执行完成后,利用计数器做一次计数,然后再去进行条件判断。如果还是true,则继续执行循环体,如果是false,就会跳出循环体,执行for循环后面的语句。

在for循环中,如果需要的初始化值不止一个,可以使用逗号运算符对它们进行分隔。例如下面这个例子中就需要在for循环中对变量i和变量j进行初始化操作,其正确的使用方法如下:

        for(int i=1, j=2; i<=10; i=i+1){
            //程序代码
        }

这里初始化了两个值,一个是i,一个是j,它们之间用“, ”隔开。但是在使用时要注意,以下几种形式是不合法的。

      for(int i=1, int j=2; 表达式;步长){  //编译错误,不能为变量个别定义数据类型
          //程序代码
      }
      for(int i=1, long j=2; 表达式;步长){    //编译错误,两个变量的数据类型不能不相同
          //程序代码
      }
      int i=1;                               //定义一个整型变量并为其赋初值为1
      for(i=1; int j=2; 表达式;步长){      //编译错误,j也需要在外部定义
          //程序代码
      }

下面来看一个例子,计算1+2! +3! +…+10!的值。

        public class ForSumTest{
            public static void main(String args[]) {
                int sum = 0;                   //将表示加和的sum初始值设置为0
                int n = 1;                     //设置n的初始值为1
                int i = 1;                     //设置i的初始值为1
                for( i = 1; i<=10; i++){         //循环10次
                    n = n*i;                   //计算n的阶乘
                    sum = sum+n;               //计算阶乘的加和
                }
                System.out.println("sum = "+sum);  //打印输出加和的值
            }
        }

在for循环中,首先将变量i赋值为1,然后判断i的值是否小于10。因为i的初始值为1,小于10,所以程序会计算n*i的值。其计算结果为1,将该结果与sum相加并将相加后的值赋给sum,此时sum的值为1(0+1),然后n值会自增1,此时n的值变为2,再进入for循环进行判断。因为2小于10,因此程序会进入循环体计算n*i的值,计算结果为2(1*2),将该结果与sum相加并将相加后的值赋给sum,此时sum的值为3(1+2),然后n值会自增1。依此类推,直到判断n的值大于10后,退出for循环。其运行结果如下:

        sum = 4037913

for循环也是可以嵌套的,例如:

        for(){
                //程序代码
                for(){
                    //程序代码
                }
        }

当然它也可以和while或do…while语句一起嵌套使用。在使用for循环时需要注意,for循环中的两个分号是必不可少的,即使循环中的某一项不写,也不能将分号去掉,例如:

      for ( ; 表达式;步长)

如果是下面这种形式,则表明程序会不断地执行循环体。

      for(; ;)

3.3 跳转控制语句

在Java中可以使用跳转语句控制循环的流程。跳转控制语句包括continue和break。goto虽然是Java的关键字,但是在实际应用中并未得到使用,但是Java使用了另外一种形式来代替goto语句,就是可以在continue和break语句中加入标号。本节主要介绍continue和break语句以及带标号的continue和break语句的用法。

3.3.1 continue语句:跳出当次循环

先来看这样一个问题,要输出0~100之间能被6整除的数,这里希望在i%6! =0的情况下,跳出当前当次循环,不执行循环体下面的语句,然后再对下一个数做循环的判断。这个时候,使用循环和分支语句就无法完成了,需要使用跳转控制语句continue。

continue的作用就是结束本次循环,将循环体剩余的部分代码跳过,然后再进行下一次循环的判断。如果判断的结果为true,则再一次执行循环体。如果判断的结果为false,则执行循环体后面的语句。

现在用continue来完成本小节开头所提出的那个问题。由于数据可能会很多,所以下面的这段代码中使用n%5==0保证每打印5个数就换一行,每两个数之间隔开一个Tab键的距离,程序代码如下:

        public class ContinueTest{
            public static void main(String args[]) {
                int n =0;                          //定义一个整型变量并为其赋初值为0
                for( int i = 0; i<=100; i++){        //循环0到100的整数
                    if(i%6! =0) continue;           //不能被6整除,就执行下一个循环体
                    n++;
                    /*判断能被6整除的n的个数,每一行只输出5个数*/
                    if(n%5==0){            //判断n的个数是否是5的倍数,如果是则做换行处理
                        System.out.print(i+"\t");
                                            //打印出能被6整除的数并隔开一个Tab键距离
                        System.out.println("");    //换行
                    }else{                         //如果不是5的倍数
                            //打印出能被6整除的数并隔开一个Tab键的距离
                            System.out.print(i+"\t");
                    }
                }
            }
        }

这里使用一个for循环,循环100次,为了打印输出能被6整除的数,在for循环里使用一个if语句,如果该值不能被6整除,就使用continue跳出本次循环,n值自增1,再进行下一次的循环判断,如果该值能被6整除,则将其打印输出,然后n值自增1,再进行下一次循环,依此类推,直到n值大于100,退出for循环。在打印输出语句中使用了System.out.print(i+ “\t”),这里的print表示不对打印的内容进行换行处理,语句里的 “\t”表示将打印的数之间隔开Tab键的距离。其运行结果如图3-10所示。

图3-10 输出0~100之间能被6整除的数的结果

该程序的运行过程为:当i=0时,由于i%6的余数为0,就将其打印输出;然后做下一次循环i=1,此时i%6的值为1,不等于0,就执行continue,跳过后面的打印语句,执行下一次循环;这时i的值变为2,再进入if语句判断i%6的值是否为0,如果不为0,就会继续执行下一次循环,依此类推,直到100以内所有能被6整除的值全都打印输出为止。

continue语句还有一种形式,就是使用带标号的continue语句。标号相当于一个标识符,可以用来指定特定的语句。使用标号时要使用冒号(:)。例如上面这个例子,如果使用带标号的continue语句,其代码如下:

        public class ContinueLabelTest{
            public static void main(String args[]) {
                outerLoop:                             //设定标号
                for(int i = 0; i<=100; i++){             //循环0到100的整数
                    if(i%6! =0) continue outerLoop;     //不能被6整除,就执行下一次循环
                    System.out.println(i);             //打印输出能被6整除的数
                }
            }
        }

这里在continue后面加了一个outerLoop标号,它用来通知计算机跳出当前循环并执行outerLoop标号处指定的循环。这段代码使用带标号的continue语句后,运行结果还是一样的。

带标号的continue语句可以控制循环的层次,尤其是在有多个嵌套循环的情况下,可以使用它跳出到任意的外层循环中。在讲完break语句之后,会给出一个带标号语句的综合例子。

3.3.2 break语句:退出当前所在循环

有些情况下,希望在循环体没有完全结束的时候,就退出循环体,执行循环体后面的语句,这时就需要使用break语句。break语句在switch语句中已经提到过,使用它可以退出switch语句,也可以使用break语句跳出循环体,提前结束循环。下面在3.3.1小节中例子的基础上,加上break语句,程序如下:

        public class BreakTest{
            public static void main(String args[]) {
                int n =0;                          //定义一个整型变量并为其赋初值为0
                for( int i = 0; i<=100; i++){        //循环0到100的整数
                    if(i==80){                     //当循环变量i的值为80时
                        break;                     //跳出循环体
                }
                    if(i%6! =0) continue;           //不能被6整除,就执行下一个循环体
                    n++;                           //将变量n的值加1
                    /*判断能被6整除的n的个数,每一行只输出5个数*/
                    if(n%5==0){            //判断n的个数是否是5的倍数,如果是则做换行处理
                        System.out.print(i+"\t"); //打印出能被6整除的数并隔开一个Tab键距离
                        System.out.println("");    //换行
                    }else{                         //如果不是5的倍数
                        /*打印出能被6整除的数并隔开一个Tab键的距离*/
                        System.out.print(i+"\t");
                    }
                }
            }
        }

在程序中加上了一个break语句,当i的值为80时,跳出for循环体,不再执行循环体里的语句,转而执行for循环之后的语句。其运行结果如图3-11所示。

图3-11 break语句运行结果

该输出结果和3.3.1小节中的结果相比,没有显示80以后的数据。和continue一样,也可以使用带标号的break语句,使用它可以退出任意的外层循环。例如上面这个例子,如果使用带标号的break语句,可以使用下面的代码完成。

        public class BreakLabelTest{
            public static void main(String args[]) {
                outLoop:                           //设定标号
                for(int i = 0; i<=100; i++){         //循环0到100的整数
                    if(i==80){                     //当循环变量i的值为80时
                        break  outLoop;            //跳出循环体
                    }
                    /*判断i是否能被6整除,如果不能被6整除则进行下一次循环*/
                    if(i%6! =0) continue ;          //如果不能被6整除则进行下一次循环
                    System.out.println(i);         //如果能被6整除打印输出该值
                }
            }
        }

这里在break后面加了一个outLoop标号,它用来通知计算机退出outLoop标号指定的循环。这里使用带标号的break语句与使用不带标号的break语句的运行结果是一样的。

3.3.3 带标号的跳转控制语句

对于continue语句来说,一般只能跳出当次循环。同样,对于break语句来说,一般也只能退出当前所在的循环。但是对于一个复杂的多层循环来说,有时需要退出其中的某一层循环,这时带标号的continue和break语句就很有用处了,可以使用它们来退出任意层次的循环。下面是一个带标号的continue语句和break语句的例子。

        public class LabelTest{
            public static void main(String args[]) {
                char c =' a' ;                               //定义并初始化字符c
                outerLoop:                                 //设定标号
                for( int i = 1; i<=5; i++){                  //循环5次
                    for( int j = 1; j<=10; j++){             //循环10次
                        /*如果给定的字符是a,则执行下一个循环体*/
                        if(c==' a' ) {
                            System.out.println(c);         //打印输出字符
                            continue outerLoop;            //执行下一个循环体
                        }else if(c==' z' ) {
                            /*如果给定的字符是z,则退出外层循环*/
                            System.out.println(c);         //打印输出字符
                            break outerLoop;               //退出外层循环
                        }else{
                            System.out.println(c);         //打印输出字符
                        }
                    }
                }
            }
        }

这段代码中定义并初始化了一个字符c,并设定了一个标号outerLoop。代码中嵌套了两层循环,外层循环循环5次,内层循环循环10次。在内层循环中对给定的字符进行判断,如果判断给定的字符是a,则打印输出该字符,并使用带标号的continue语句告诉计算机跳出当前的循环执行指定标号outerLoop处的循环。如果判断给定的字符是z,则打印输出该字符,并使用带标号的break语句告诉计算机退出outerLoop标号指定的外层循环。如果判断给定的字符既不是a也不是z,就将其按照正常的循环打印输出。

这里将字符首先赋初值为a,按照程序它将执行带有outerLoop标号的continue语句,其运行结果如图3-12所示。

图3-12 执行带有outerLoop标号的continue语句

从运行结果来看,程序共打印输出了5次字符a。这是因为当编译器判断给定的字符是a的时候,首先会将其打印输出,然后执行带有outerLoop标号的continue语句。此时标号outerLoop是一个表示外层循环的标志,这样程序就会跳出当前的内层循环,转而执行标号所在的外层循环。这样外层循环的变量i的值就会加1,然后再执行内层循环,如此反复。因此在内层循环中字符a只会被打印一次,就会跳出内层循环,由于外层循环需要循环5次,所以最后字符a会打印输出5次。

明白了带有outerLoop标号的continue语句,那么理解带有outerLoop标号的break语句的结果就并不困难了。这里可以在程序中将字符c的初值修改为z,然后再编译运行一下程序,看一下结果是否和读者想的一样。其运行结果如图3-13所示。

图3-13 执行带有outerLoop标号的break语句

从运行结果来看,程序只打印输出了1次字符z。这是因为当编译器判断给定的字符是z的时候,首先会将其打印输出,然后执行带有outerLoop标号的break语句,由于标号outerLoop是一个表示外层循环的标志,因此程序就会直接退出该标号所表示的外层循环,这样字符z就只会打印输出1次了。

3.4 综合应用程序举例

Java的流程控制语句是程序设计中经常用到的,使用不同的流程控制语句以及循环之间的嵌套可以解决许多实际的问题。本节将给出两个贴近实际的例子,并综合运用前面讲过的分支、循环和跳转语句解决这两个实际问题。

3.4.1 测试你的体重是否标准

BMI是Body Mass Index的缩写,是通过身高和体重计算出来的一个指数。由于BMI计算的是身体脂肪的比例,所以在测量身体因超重而面临心脏病、高血压等风险上,比单纯的以体重来认定更具准确性。BMI的计算标准规定如下。

标准体重:22×身高(米)的平方

体重指数:体重(公斤)/身高(米)的平方

正常体重:体重指数18~25

超重:体重指数25~30

轻度肥胖:体重指数 > 30

中度肥胖:体重指数 > 35

重度肥胖:体重指数 > 40

根据BMI的测试标准编写的代码如下:

        import java.io.*;
        public class WeightTest{
            public static void main(String args[]) throws IOException{
                /*以下6句用来读取键盘上输入的数据*/
                InputStreamReader reader = new InputStreamReader(System.in);
                BufferedReader bf = new BufferedReader(reader); //创建字符输入流对象
                System.out.print("put the hight(m):" );        //在键盘上输入身高
                String h = bf.readLine();                     //读取从键盘上输入的身高
                System.out.print("put the weight(kg):" );      //在键盘上输入体重
                String w = bf.readLine();                     //读取从键盘上输入的体重
                /*将键盘上输入的数据转换为double类型*/
                double hight = Double.parseDouble(h);  //将输入身高转换为double类型值
                double weight = Double.parseDouble(w); //将输入体重转换为double类型值
                /*利用读取到的键盘数据来计算BMI和标准体重*/
                double BMI = weight/(hight*hight);     //计算BMI的值
                double  normalWeight = 22*hight*hight; //计算输入身高的标准体重
                /*打印输出计算的标准体重和BMI的结果*/
                //打印输出计算的标准体重
                System.out.println("您的身高对应标准体重应该为"+ normalWeight);
                System.out.println("您的BMI指数为"+(int) BMI); //打印输出BMI指数
                /*根据BMI的指数进行判断,并打印输出相应的内容*/
                if(BMI>=18.0&&BMI<=25.0){              //如果BMI的值在18.0到25.0之间
                    System.out.println("您的体重很标准。" );     //打印输出括号中的语句
                }else if(BMI>25.0&&BMI<=30.0){         //如果BMI的值在25.0到30.0之间
                    //打印输出括号中的语句
                    System.out.println("您的体重有些超重。请注意身体" );
                }else if(BMI>30.0&&BMI<=35.0){         //如果BMI的值在30.0到35.0之间
                    //打印输出括号中的语句
                    System.out.println("您有些轻度肥胖,应该注意锻炼了" );
                }else if(BMI>35.0&&BMI<=40.0){         //如果BMI的值在35.0到40.0之间
                    //打印输出括号中的语句
                    System.out.println("您属于中度肥胖,要经常锻炼身体了" );
                }else if(BMI>40.0){                    //如果BMI的值大于40.0
                    //打印输出括号中的语句
                    System.out.println("您属于重度肥胖,应该加强锻炼了" );
                }else{                                 //如果BMI的值不在此范围内
                    System.out.println("没有可供参考的数据,请确认输入的数据是否正确" );
                }
            }
        }

这里首先使用I/O操作读取从键盘中输入的字符串并将读取到的值转换为double类型。然后使用开始讲到的计算标准体重和BMI的方法对其进行计算,并打印输出标准体重和BMI的结果。最后根据计算得到的BMI值进行判断,对不同的BMI值打印不同的提示信息。其运行结果如图3-14所示。

图3-14 标准体重测试的运行结果

3.4.2 随机彩票模拟程序

下面这个程序是一个简单的随机彩票模拟程序,它模拟的是从40个整数之间随机选择6个作为彩票的一组号码。这个程序首先会要求输入一个1~5的整数,通过输入的整数可以一次最多产生5组号码。这里使用数组来存放每一组所产生的号码。数组可以用来存放相同数据类型的数据,有关数组的具体使用方法在第4章中会讲到,这里先借用一下数组的概念。随机彩票模拟程序的代码如下:

        import java.io.*;
        public class  LotteryTicketTest {
            public static void main(String args[]) throws IOException{
                /*以下4句用来读取键盘上输入的数据*/
                InputStreamReader reader = new InputStreamReader(System.in);
                BufferedReader bf = new BufferedReader(reader); //创建字符输入流对象
                System.out.print("put the number of 1-5:" );   //在键盘上输入字符
                String s = bf.readLine();                     //读取从键盘上输入的字符
                /*将读取到的键盘数据转换为整型*/
                int ticketNumber = Integer.parseInt(s);    //将键盘上输入的值转换为整型
                /*在输入的number小于等于5的情况下*/
                if(ticketNumber<=5){
                    int m = 0;                             //初始化表示彩票组数m的值
                    int ch[] = new int[6];                 //定义一个长度为6的数组
                    for(int k =1; k<=ticketNumber; k++){    //循环键盘输入的值的次数
                          m = m+1;                          //确定彩票的组数
                        /*循环6次每次产生一个随机数放入到数组中*/
                        for (int i = 0; i < 6; i++) {      //循环6次
                            ch[i] = (int) (Math.random() * 40 + 1);
                                                            //随机选取一个数放入数组中
                            for (int j = 0; j < i; j++) {
                                /*如果随机选取的数相等的话,将i减1,重新选择数据*/
                                if (ch[i] == ch[j]) {      //如果随机选取的数相等
                                    i--;                   //选取彩票的次数减1
                                    continue;              //跳出本次循环,进行下一次循环
                                }
                            }
                        }
                        if(m==1){                          //当产生一组彩票时
                            //打印输出括号中的语句
                            System.out.println("40选6的号码为:");
                        }else{                             //当产生多组彩票时
                            System.out.println(" ");       //换行
                        }
                        /*循环6次,将得到的6个数打印输出*/
                        for (int i = 0; i < 6; i++) {              //循环6次
                            System.out.print(ch[i] + " ");     //将得到的6个数打印输出
                        }
                    }
                }else{
                /*如果输入的值不是1到5之间的数,则要重新输入*/
                //打印输出重新输入数据信息
                System.out.println("输入数据只能是1~5,请重新输入");
                }
            }
        }

在这个程序中,最多可以产生5组随机的彩票,所以首先判断输入的值是否合法。如果输入的值合法,就随机产生一组号码。产生号码时,最外层的for循环用来控制产生彩票的组数,内层又嵌套了3个for循环,第一层嵌套的for循环要产生6个号码,第二层嵌套的for循环用来判断产生的这组号码是否有重复的,最后一个for循环用来将得到的号码打印输出。

在随机选取彩票的过程中,一个基本原则是一组号码不能有重复的数据出现。因此要产生一组号码就要在随机数据产生后进行判断,如果发现一组里有相等的数据,也就是发现当ch[i]==ch[j]的时候,这时程序会让i-1,并用continue跳出内层的循环体,执行外层的for循环,再产生一个随机数。这里定义了一个整型变量m,定义m是为了让显示的每一行只产生一组数据,当m=1时,即当产生一组彩票时打印一次提示输出的信息,当m>1时,即有多组彩票时,就将它们换行输出。最后利用一个for循环将产生的一组数据从数组中打印出来,这样就完成了一组号码的产生,也就结束了一次最外层的for循环。如果产生多组号码,那么程序就会按照此方法循环多次。其运行结果如图3-15所示。

图3-15 随机彩票模拟运行结果

读者可能会注意到,每一组随机产生的号码是无序的,并没有按照数字从小到大的顺序排列,在学完第4章之后,这个问题就可以解决了。

3.5 小结

本章介绍了程序设计中经常应用到的各种流程控制结构,包括分支控制语句中的if语句和switch语句,循环控制语句中的while语句、do…while语句和for语句,以及跳转控制语句中的continue语句和break语句。另外,还介绍了带标号的continue语句和break语句的使用方法。通过本章的学习,希望读者对这些流程控制语句能够有一个较为全面的认识。