流程控制对于任何一门编程语言来说都是至关重要的,它提供了控制程序步骤的基本手段。如果没有流程控制语句,整个程序将按照线性的顺序来执行,不能根据用户的输入决定执行的序列。

1.顺序结构

Java程序是从上到下逐行执行语句,中间没有任何判断和跳转。

2.分支结构(选择语句)

  • 根据条件,选择性地执行某段代码。
  • if…elseswitch-case两种分支语句。

2.1 if……else2.1.1 基本语法

  • 单分支条件判断:if

    • 格式:

      if(条件表达式){  代码块; //如果条件表达式的值为true,将执行这部分语句}
    • 说明: 条件表达式必须是布尔表达式(关系表达式或逻辑表达式)或布尔变量。

    • 执行流程:

      1. 首先判断条件表达式的结果是true还是false;

      2. 如果是true就执行代码块;

      3. 如果是false就不执行代码块;

  • 双分支条件判断:if……else

    • 格式:

      if(布尔表达式){   代码块1; //如果布尔表达式的值为true,执行代码块1}else{   代码块2; //如果布尔表达式的值为false,执行代码块2}
    • 执行流程:

      1. 首先判断条件表达式看其结果是true还是false
      2. 如果是true就执行代码块1
      3. 如果是false就执行代码块2
  • 多分支条件判断:**if……else if……else if **

    • 格式:

      if(布尔表达式 1){   //如果布尔表达式 1的值为true执行代码}else if(布尔表达式 2){   //如果布尔表达式 2的值为true执行代码}else if(布尔表达式 3){   //如果布尔表达式 3的值为true执行代码}…… else {   //如果以上布尔表达式都不为true执行代码}
    • 说明:

      • if 语句至多有 1 个 else 语句,else 语句在所有的 else if 语句之后。
      • if 语句可以有若干个 else if 语句,它们必须在 else 语句之前。
      • 一旦其中一个 else if 语句检测为 true,其他的 else if 以及 else 语句都将跳过执行。
      • 如果没有任何关系表达式为true,就执行else中的语句块,然后结束当前多分支。

2.1.2 应用举例

案例1:成年人心率的正常范围是每分钟60-100次。体检时,如果心率不在此范围内,则提示需要做进一步的检查。

int heartRate = 120; //声明心跳次数变量并赋值//单分支条件判断:if的练习使用if(heartRate >= 60 || heartRate <= 100) {System.out.println("心率不正常,需要做进一步的检查");}System.out.println("检测结束");

案例2:定义一个整数,判定是偶数还是奇数

public class IfElseExer02 {    public static void main(String[] args) {        int a = 2;//定义一个整数变量a,并赋值为2                //使用if……else,判断一个整数的奇偶        if(a % 2 == 0) {            System.out.println("a是偶数");        }else {            System.out.println("a是奇数");        }    }}

案例3:

岳小鹏参加Java考试,他和父亲岳不群达成承诺。如果:成绩为100分时,奖励一辆跑车;成绩为(80,99]时,奖励一辆山地自行车;当成绩为[60,80]时,奖励环球影城一日游;其它时,胖揍一顿。

说明:默认成绩是在[0,100]范围内

public class IfElseExer03 {    public static void main(String[] args) {        int grade = 66; //声明成绩变量,并赋值为66                //使用多分支条件判断:if……else if……else来完成案例3        if(grade == 100) {            System.out.println("奖励一辆跑车");        }else if(grade >80 && grade = 60 && grade <= 80) {            System.out.println("奖励环球影城一日游");        }else {            System.out.println("胖揍一顿");        }    }}

2.1.3 if……else嵌套

在 if 的语句块中,或者是在else语句块中,又包含了另外一个条件判断(可以是单分支、双分支、多分支),就构成了嵌套结构

执行的特点:
(1)如果是嵌套在if语句块中的,只有当外部的if条件满足,才会去判断内部的条件
(2)如果是嵌套在else语句块中的,只有当外部的if条件不满足,进入else后,才会去判断内部的条件

if(布尔表达式 1){   //如果布尔表达式 1的值为true执行代码   if(布尔表达式 2){      //如果布尔表达式 2的值为true执行代码   }}
//if……else嵌套的小练习public class IfElseExer04 {    public static void main(String[] args) {        int x = 30;        int y = 10;        if(x == 30) {            if(y == 10) {                System.out.println("X = 30 "+"Y = 10");            }        }    }}

if……else嵌套语句的案例小练习:

/*由键盘输入三个整数分别存入变量num1、num2、num3,对它们进行排序(使用 if-else if-else),并且从小到大输出。*/public class IfElseExer05 {    public static void main(String[] args) {        //使用Scanner类接收三个整数并分别赋值给变量num1、num2、num3        System.out.println("请输入3个整数:");        Scanner sc = new Scanner(System.in);        int num1 = sc.nextInt();        int num2 = sc.nextInt();        int num3 = sc.nextInt();        //使用if……else嵌套语句实现判断输入的三个整数大小,并按从小到大的排序打印        if(num2 >= num1) {            if(num3 >= num2) {                System.out.println(num1+"<"+num2+"<"+num3);            }else if(num3 <= num1) {                System.out.println(num3+"<"+num1+"<"+num2);            }else {                System.out.println(num2+"<"+num3+"<"+num1);            }        }else { //num2 = num1) {                System.out.println(num2+"<"+num1+"<"+num3);            }else if(num3 <= num2) {                System.out.println(num3+"<"+num2+"<"+num1);            }else {                System.out.println(num2+"<"+num3+"<"+num1);            }        }    sc.close();    }}

2.2 switch-case分支(选择)结构2.2.1 基本语法

  • 语法格式

    switch(expression) {    case value :       //执行语句1       break; //可选    case value :       //执行语句2       break; //可选    …… //你可以有任意数量的case语句    default : //可选       //语句}
  • 执行流程图:

  • 执行过程:

    1. 根据switch中表达式的值,依次匹配各个case。如果表达式的值等于某个case中的常量值,则执行对应case中的执行语句。

    2. 执行完此case的执行语句以后,
      -如果遇到break,则执行break并跳出当前的switch-case结构
      -如果没有遇到break,则会继续执行当前case之后的其它case中的执行语句。—>case穿透


      -直到遇到break关键字或执行完所有的case及default的执行语句,跳出当前的switch-case结构。

  • switch-case语句的使用有如下规则:

    • switch 语句中的变量类型是: byte、short、int 、char。从 Java SE 7 开始,switch 支持字符串 String 类型了,同时 case 标签必须为字符串常量或字面量。
    • switch 语句可以拥有多个 case 语句。每个 case 后面跟一个要比较的值和冒号。
    • case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量。
    • 当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句。
    • 当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。
    • switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句。

2.2.2 应用举例

public class Test {   public static void main(String args[]){            char grade = 'C';      switch(grade) {         case 'A' :            System.out.println("优秀");             break;         case 'B' :         case 'C' :            System.out.println("良好");            break;         case 'D' :            System.out.println("及格");            break;         case 'F' :            System.out.println("差");            break;         default :            System.out.println("成绩等级错误");      }      System.out.println("你的等级是 " + grade);   }}

案例:

使用switch-case实现对学生成绩大于60分的,输出“合格”。低于60分的,输出“不合格”。

public class SwitchCaseExer03 {    public static void main(String[] args) {        int grade = 61; //声明成绩变量,并赋值为61        //使用switch-case分支语句实现案例3        switch (grade / 60) {            case 0:                System.out.println("成绩不合格");                break;            case 1:                System.out.println("及格");                break;            default:                System.out.println("成绩格式错误");        }    }}

2.2.3 switch-case中的case穿透特性

在switch语句中,如果case的后面不写break,将出现穿透现象,也就是一旦匹配成功,不会在判断下一个case的值,直接向后运行,直到遇到break或者default或者运行完所有case才终止,执行终止。

我们可以利用这个特性实现某些功能,或者解决某些问题。

案例:编写程序:从键盘上输入2023年的“month”和“day”,要求通过程序输出输入的日期为2023年的第几天。

public class SwitchCaseExer04 {    public static void main(String[] args) {        //使用Scanner,从键盘接收2023年的月、日        Scanner scan = new Scanner(System.in);        System.out.println("请输入当前月份:");        int month = scan.nextInt(); //阻塞式方法        System.out.println("请输入日期:");        int day = scan.nextInt();        int sumDays = 0; //记录总天数        //使用switch-case分支语句实现,通过程序输出输入的日期为2023年的第几天        switch(month) {            case 1:                sumDays = day;                break;            case 2:                sumDays = day +30;                break;            case 3:                sumDays = day + 30+ 28;                break;            case 4:                sumDays = day + 30 + 28 + 31;                break;            case 5:                sumDays = day + 30 + 28 + 31 + 30;                break;            case 6:                sumDays = day + 30 + 28 + 31 + 30 + 31;                break;            case 7:                sumDays = day + 30 + 28 + 31 + 30 + 31 + 30;                break;            case 8:                sumDays = day + 30 + 28 + 31 + 30 + 31 + 30 + 31;                break;            case 9:                sumDays = day + 30 + 28 + 31 + 30 + 31 + 30 + 31 + 31;                break;            case 10:                sumDays = day + 30 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30;                break;            case 11:                sumDays = day + 30 + 28 + 31 + 30 + 31 + 30 + 31 + 31+ 30 + 31;                break;            case 12:                sumDays = day + 30 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30;                break;        }        System.out.println("当前日期为:2023年"+month+"月"+day+"日"+",日期为2023年的第"+sumDays+"天");        scan.close();    }}

上面例子我们可知代码中重复写了很多边遍相同的数据,数据冗余。我们可以利用case的穿透性解决这个问题如下:

public class SwitchCaseExer05 {    public static void main(String[] args) {        //使用Scanner,从键盘接收2023年的月、日        Scanner scan = new Scanner(System.in);        System.out.println("请输入当前月份:");        int month = scan.nextInt(); //阻塞式方法        System.out.println("请输入日期:");        int day = scan.nextInt();        int sumDays = 0; //记录总天数        //使用switch-case分支语句实现,通过程序输出输入的日期为2023年的第几天,利用了case穿透性        switch(month) {            case 12:                sumDays += 30;//这个30是代表11月份的满月天数            case 11:                sumDays += 31;//这个31是代表10月份的满月天数            case 10:                sumDays += 30;//这个30是代表9月份的满月天数            case 9:                sumDays += 31;//这个31是代表8月份的满月天数            case 8:                sumDays += 31;//这个31是代表7月份的满月天数            case 7:                sumDays += 30;//这个30是代表6月份的满月天数            case 6:                sumDays += 31;//这个31是代表5月份的满月天数            case 5:                sumDays += 30;//这个30是代表4月份的满月天数            case 4:                sumDays += 31;//这个31是代表3月份的满月天数            case 3:                sumDays += 28;//这个28是代表2月份的满月天数            case 2:                sumDays += 31;//这个31是代表1月份的满月天数            case 1:                sumDays += day;//这个day是代表当月的第几天        }        System.out.println("当前日期为:2023年"+month+"月"+day+"日"+",日期为2023年的第"+sumDays+"天");        scan.close();    }}

3.循环结构(循环语句)

  • 根据循环条件,重复性的执行某段代码。
  • forwhiledo-while三种循环语句。
  • 根据循环条件,重复性的执行某段代码。
  • forwhiledo-while三种循环语句。
  • 补充:JDK5.0 提供了foreach循环,方便的遍历集合、数组元素。
  • 循环结构的四个要素:
    • 初始化条件
    • 循环条件
    • 循环体
    • 迭代部分

3.1 while循环3.1.1 基本语法

语法格式:

初始化部分while(条件表达式) {    循环体;    迭代语句;}

说明:

  • while(循环条件)中循环条件必须是boolean类型;
  • 注意不要忘记声明迭代部分。否则,循环将不能结束,变成死循环。
  • for循环与while循环的区别:初始化条件部分的作用域不同。

3.1.2 应用举例

案例1:计算1~1000的相加结果

public class WhileExer02 {    public static void main(String[] args) {        //使用while循环计算1到1000的相加结果        int i = 1;        int sum = 0;        while(i <= 1000) {            sum += i;            i++;        }        System.out.println("1~1000的相加结果为:"+sum);    }}

案例2:遍历1-100的偶数,并计算所有偶数的和、偶数的个数(累加的思想)

public class WhileExer03 {    public static void main(String[] args) {        int i = 1;        int sum = 0; //声明变量sum,用于存储所有的偶数和,并初始化值为0        int count = 0; //声明变量count,用于存储偶数的个数,并初始化为0        //使用while循环,实现1~100的偶数遍历,并计算所有偶数的和以及偶数的个数        while(i <= 100) {            if(i % 2 == 0){                System.out.println(i);                sum += i;                count++;            }            i++;        }        System.out.println("所有偶数的和为:"+sum+'\n'+"偶数的个数为:"+count);    }}

3.3 do……while循环3.3.1 基本语法

语法格式:

do {    循环体语句;    迭代语句;}while(条件表达式);

说明:

  • 结尾while(循环条件)中循环条件必须是boolean类型;
  • do{}while();最后有一个分号;
  • do-while结构的循环体语句是至少会执行一次,这个和for和while是不一样的;
  • do……while语句和while语句的区别:
    • while循环语句是先判断条件是否成立再执行循环体;
    • do……while是先执行一次循环体后,再判断条件是否成立,也就是说do……while语句”{}“中的程序段至少要执行一次

3.3.2 应用举例

案例1:遍历1-100的偶数,并计算所有偶数的和、偶数的个数(累加的思想)

public class DoWhileExer {    public static void main(String[] args) {        int i = 1;        int sum = 0; //存偶数的和        int count = 0; //存偶数的个数        //使用do……while循环语句实现遍历1-100的偶数,并计算所有偶数的和、偶数的个数(累加的思想)        do {            if(i % 2 == 0){                System.out.println(i);                sum += i;                count++;            }            i++;        }while(i <= 100);        System.out.println("sum = "+sum);        System.out.println("count = "+count);    }}

3.4 for循环3.4.1 基本语法

for(表达式1;表达式2;表达式3) {    循环体;}

表达式1:初始化表达式,负责完成变量的初始化;

表达式2:循环条件表达式,值为boolean型表达式,指定循环条件。等同于while循环()里的表达式;

表达式3:每次循环结束后执行的语句,通常用来改变循环条件,迭代部分;

3.4.2 应用举例

案例1:使用for循环重复执行某些语句

题目:输出5行HelloWorld

public class ForExer01 {    public static void main(String[] args) {        int i; //声明变量i,用于存储for循环中的初始化表达式的值        //使用for循环语句打印五次HelloWorld!        for(i = 1 ; i <= 5;i++) {            System.out.println("HelloWorld!");        }    }}

案例2:利用输出语句学习for循环语句的执行过程

public class ForExer02 {    public static void main(String[] args) {        int num = 1;        for(System.out.print("a"); num < 4; System.out.println("b"),num++) {            System.out.print("c");        }                System.out.println(); //换行        System.out.println("num = "+num);    }}

总结:从运行结果我们可知这个例子中的for循环执行过程是:表达式1–>>表达式2(值为true)–>>循环体–>>表达式3–>>表达式2(true)–>>循环体–>>表达式3–>>表达式2(true)–>>循环体–>>表达式3–>>表达式2(false)–>>for循环结束。

案例3:使用for循环计算2~100以内所有的偶数的和

public class ForExer06 {    public static void main(String[] args) {        int sum = 0; //存偶数相加的和              for(int i = 2; i <= 100; i += 2){        sum += i;        }        System.out.println("所有偶数的和为:"+sum);    }}

3.5 循环控制

循环控制包含两方面的内容,一方面是控制循环变量的变化方式,另一方面是控制循环的跳转。

控制循环的跳转需要用到breakcontinue两个关键字,这两条跳转语句的跳转效果不同,break语句是中断循环,continue语句是跳过此次循环执行下一次循环。

3.5.1 break

使用break语句可以跳出switch……case结构。在循环结构中,同样可以用break语句跳出当前循环体,从而中断当前循环。

//输出1~20出现的第一个偶数//for循环使用break语句跳出循环public class BreakExer01 {    public static void main(String[] args) {        for(int i = 1; i <=20; i++) {            if(i % 2 == 0) {                System.out.println("1~20出现的第一个偶数:"+i);                break;            }        }    }}

3.5.2 continue

continue语句是针对break语句的补充。continue不是立即跳出循环体,而是跳过本次循环,回到循环的条件判断部分,重新开始执行循环。在for循环中遇到continue后,首先执行循环的增量部分。然后进行条件判断。在while和do……while循环中,continue语句使控制直接回到条件判断部分。

// 编写一个for循环从1循环至20,如果当前循环的次数为偶数,则使用continue语句跳过循环public class Continue01 {    public static void main(String[] args) {        for(int i = 1; i <= 20; i++) {            if(i % 2 == 0) {                continue;            }            System.out.println(i);        }    }}