七、Java 的流程控制语句(选择结构)

流程是人们生活中不可或缺的一部分,它表示人们每天都在按照一定的流程做事。比如出门搭车、上班、下班、搭车回家。这其中的步骤是有顺序的。程序设计也需要有流程控制语句来完成用户的要求,根据用户的输入决定程序要进入什么流程,即“做什么”以及“怎么做”等。

1 三种基本的程序流程结构

从结构化程序设计角度出发,程序有 3 种结构:顺序结构、选择结构、循环结构

  • 顺序结构:程序按顺序执行,不发生跳转

  • 选择结构:依据条件是否满足,有选择的执行相应功能

  • 循环结构:依据条件是否满足,循环多次执行某段代码

到目前为止,我们所编写的程序都属于顺序结构。但是事物的发展往往不会遵循早就设想好的轨迹进行,因此,所设计的程序还需要能够具有在不同的条件下处理不同问题以及当需要进行一些相同的重复操作时,如何能省时省力地解决问题的能力。

2 表达式、语句和块

为了能更加方便地学习之后的内容,让我们先来了解 Java 中的三个基础概念:表达式语句

2.1 表达式

简单地说,如果一段代码,可以作为一个整体,看做一个值,那么,这段代码就是表达式。表达式可以出现在赋值符号(=)右侧。

除函数调用外,大部分表达式不能直接作为语句出现,而是作为语句的一部分出现。

以下是一些表达式的例子:

3.1415926
(a + b) / 2
x * y * z - y + (20 - x)

2.2 语句

在 Java 中,语句是最小的组成单位,每个语句必须使用分号作为结束符。除此之外,Java 对语句无任何其他限制,开发人员可以很随意地用符合自己风格的方式编写语句。

例如,可以将一个语句放在多行中,示例如下:

String str = "Apple "
+"Banner "+"Pear "
+" Orange";

由于 Java 使用分号作为语句的结束符,所以上面的 3 行代码会被 Java 认为是一条语句,因为这 3 行中只有一个分号。但是,我们不推荐使用这种方式来编写语句,这样写并不美观,我们只应在语句过长时,适当使一条语句占用多行。

同样,因为使用分号作为分隔符,将多个语句放在一行来编写也是允许的。例如,下面的示例代码也是正确的。

int a=0,b,c;b=a+10;b++;c=a*b;System.out.println(c);

上面将 5 个语句放在一行中。

甚至,存在一种特殊情况,仅仅是一个单独的分号,也是一个语句,被称为 “空语句” 。空语句在程序中什么也不做,没有实际作用,往往只作为一种占位符出现。

2.3 语句块

语句块,又称为 “复合语句” ,是多个语句的组合,但这个整体,可以从语法上可以被视为一条语句。

语法

{
    // 语句列表
}

例子

{
    width = 10; // 为width变量赋值
    height = 90; // 为height变量赋值
    area = width * height; // 计算width变量和height变量的乘积
}

3 选择结构

选择结构(也叫分支结构)解决了顺序结构不能判断的缺点,可以根据一个条件判断执行哪些语句块。Java 支持两种选择语句:if 语句和 switch 语句。

3.1 if 语句

3.1.1 单 if 结构

if 语句是使用最多的条件分支结构,它属于选择语句,也可以称为条件语句。

if 选择结构是先进行条件判断,之后再做处理的一种语法结构。默认情况下,if 语句控制着下方紧跟的一条语句的执行。不过,通过语句块,if 语句可以控制多个语句。

if 语句的最简语法格式如下,表示“如果满足某种条件,就进行某种处理”。

语法:

if (条件表达式) {
    语句块;
}

其中“条件表达式”和“语句块”是比较重要的两个地方。

  • 条件表达式:条件表达式可以是任意一种逻辑表达式,最后返回的结果必须是一个布尔值。取值可以是一个单纯的布尔变量或常量,也可以是使用关系或布尔运算符的表达式。如果条件为真,那么执行语句块;如果条件为假,则语句块将被绕过而不被执行。

  • 语句块:该语句块可以是一条语句也可以是多条语句。如果仅有一条语句,可省略条件语句中的大括号 {}。当从编程规范角度不要省略大括号,省略大括号会使程序的可读性变差。

if 条件语句的运行流程如图所示。

3-1P92Q50459617.jpg例子:

编写一个 Java 程序,允许用户从键盘输入一个数字,再判断该数是否大于 100。使用 if 语句的实现代码如下:

public static void main(String[] args) {
    System.out.println("请输入一个数字:");
    Scanner input = new Scanner(System.in);
    int num = input.nextInt(); // 接收键盘输入数据
    // 判断用户输入的数据是否大于100
    if (num > 100) {
        System.out.println("输入的数字大于100");
    }
    // 判断用户输入的数据是否等于100
    if (num == 100) {
        System.out.println("输入的数字等于100");
    }
    // 判断用户输入的数据是否小于100
    if (num < 100) {
        System.out.println("输入的数字小于100");
    }
}

3.1.2 if-else 结构

if 结构只能定义一个操作:当满足条件时,执行代码块中的代码。

ifelse 配合,形成 if-else 结构,就可以定义两个操作:当满足条件时,执行一段代码,否则,执行另一段代码。

语法:

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

在上述语法格式中,如果 if 关键字后面的表达式成立,那么就执行语句块 1,否则的话则执行语句块 2,其运行流程如图所示。

if…else 运行流程.jpg例子:

实现比较 num1 和 num2 的大小,使用 if…else 双条件来实现,具体代码如下:

public static void main(String[] args) {
    int num1 = 50;
    int num2 = 34;
    // 如果num1大于num2
    if (num1 > num2) {
        System.out.println("num1大于num2");
    } else {
        // 否则就是num1小于或等于num2
        System.out.println("num1小于或等于num2");
    }
}

双条件语句减少了代码的编写量,同时增强了程序的可读性,更重要的是,因为减少了一次判断,程序的运行效率更高了。

3.1.3 多条件 if-else-if 结构

if 语句的主要功能是给程序提供一个分支。然而,有时候程序中仅仅多一个分支是远远不够的,甚至有时候程序的分支会很复杂,这就需要使用多分支的 if-else-if 语句。

通常表现为“如果满足某种条件,就进行某种处理,否则如果满足另一种条件才执行另一种处理……,这些条件都不满足则执行最后一种条件”。

if-else-if 多分支语句的语法格式如下所示:

if(表达式1) {
    语句块1;
} else if(表达式2) {
    语句块2;
...
} else if(表达式n) {
    语句块n;
} else {
    语句块n+1;
}

可以看出,else-if 结构实际上是 if-else 结构的多层嵌套。明显的特点就是在多个分支中只执行一个语句组,而其他分支都不执行,所以这种结构可以用于有多种判断结果的分支中。

在使用 if-else-if 语句时,依次判断表达式的值,当某个分支的条件表达式的值为 true 时,则执行该分支对应的语句块,然后跳到整个 if 语句之外继续执行程序。如果所有的表达式均为 false,则执行语句块 n+1,然后继续执行后续程序,其运行流程如图所示。

if…else if 语句的执行流程.jpg例子:

假设某学校对成绩的判断标准是:不低于 90,可以评为优秀;低于 90 但不低于 80,可以评为良好;低于 80 但不低于 60,可以评为中等;否则评为差。

public static void main(String[] args) {
    System.out.println("请输入考试成绩:");
    Scanner input = new Scanner(System.in);
    int score = input.nextInt(); // 接收键盘输入数据
    if (score >= 90) { // 考试成绩>=90
        System.out.println("优秀");
    } else if (score >= 80) { // 90>考试成绩>=80
        System.out.println("良好");
    } else if (score >= 60) { // 80>考试成绩>=60
        System.out.println("中等");
    } else { // 考试成绩<60
        System.out.println("差");
    }
}

当考试成绩为 90 分以上时,则执行第一个 if 语句,下面的 3 个条件判断语句不会执行;当考试成绩为 80 分以上 90 分以下时,则执行第一个 else if 语句;当考试成绩在 60~80 分,并且包含 60 分的成绩,则执行第二个 else if 语句;如果上述 3 个条件都不满足,则执行 else 语句。

3.1.4 if 的嵌套使用

if 语句的用法非常灵活,不仅可以单独使用,还可以在 if 语句里嵌套另一个 if 语句。同样,if…else 语句和 if…else if 语句中也可以嵌套另一个 if 结构的语句,以完成更深层次的判断。

嵌套 if 的语法格式如下:

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

在上述格式中,应该注意每一条 else 与离它最近且没有其他 else 对应的 if 相搭配,其执行流程如图所示。

嵌套 if 语句执行流程.jpg例子:

活动计划安排,如果今天是工作日,去上班;如果今天是周末,则出去游玩;同时,如果周末天气晴朗,去室外游乐场游玩,否则去室内游乐场游玩。实现代码如下:

public static void main(String[] args) {
    String today = "周末";
    String weather = "晴朗";
    if (today.equals("周末")) {
        if (weather.equals("晴朗")) {
            System.out.println("去室外游乐场游玩");
        } else {
            System.out.println("去室内游乐场游玩");
        }
    } else {
        System.out.println("去上班");
    }
}

如上述代码所示,today 满足 if 语句的“today.equals("周末")”条件,接着测试 weather 是否满足“weather.equals("晴朗")”条件,满足该条件输出“去室外游乐场游玩”。

3.2 三元运算符

三元运算符( ? : ),又称 “三目运算符” 。我们之前接触过 “一元运算符” 、 “二元运算符”,那么大家应该猜到,三元运算符需要用到三个操作数。

三元运算符可以视为 if-else 结构的简写,不同的是,三元运算符终究是一种运算符,它的操作数必须是可被视为值的表达式,而三元运算符所构成的也是一个表达式,它作为整体可被视为一个值。

语法:

(值为布尔值的表达式0) ? 表达式1 : 表达式2 

如果表达式 0 的结果为 true ,那么三元运算符构成的表达式值为表达式 1 的值;

如果表达式 0 的结果为 false ,那么三元运算符构成的表达式值为表达式 2 的值;

例子:

用三元运算符取两个数的最大值。

public class Hello {
    public static void main(String[] args) {
        int value1 = 1;
        int value2 = 2;
        int max = (value1 > value2) ? value1 : value2;
        System.out.println(max);
    }
}

3.3 switch 语句

if…else 语句可以用来描述一个“二岔路口”,我们只能选择其中一条路来继续走,然而生活中经常会碰到“多岔路口”的情况。switch 语句提供了 if 语句的一个变通形式,可以从多个语句块中选择其中的一个执行。

switch 语句是 Java 的多路分支语句。它提供了一种基于一个表达式的值来使程序执行不同部分的简单方法。因此,它提供了一个比一系列 if-else-if 语句更好的选择。

switch 语句的基本语法形式如下所示:

switch(表达式) {
    case 值1:
        语句块1;
        break;
    case 值2:
        语句块2;
        break;
    …
    case 值n:
        语句块n;
        break;
    default:
        语句块n+1;
    break;
}

其中,switchcasedefaultbreak 都是 Java 的关键字。

switch

“开关”,这个开关就是 switch 关键字后面小括号里的值,小括号里要放一个 byteshortintcharString类型的表达式。

case

“情况,情形”,case 标签的内容可以是与 switch 后面小括号内表达式类型相同的常量表达式枚举常量字面量,不可以是变量

注意:重复的 case 值是不允许的。

default

“默认”,即其他情况都不满足。default 后要紧跟冒号,default 块和 case 块的先后顺序可以变动,不会影响程序执行结果。通常,default 块放在末尾,也可以省略不写。

break

“跳出”,即跳出当前 switch 结构。

如果在 case 分支语句的末尾没有 break 语句,那么就会接着执行下一个 case 分支语句。这种情况常常会引发错误,但有时这也能帮助我们更好地完成我们的程序。

switch 语句的执行过程如下:表达式的值与每个 case 语句中的常量作比较。如果发现了一个与之相匹配的,则执行该 case 语句后的代码。如果没有一个 case 常量与表达式的值相匹配,则执行 default 语句。当然,default 语句是可选的。如果没有相匹配的 case 语句,也没有 default 语句,则什么也不执行。

switch语句执行流程图.jpg 例子:

在节目的抽奖环节里,节目组会根据每位嘉宾的座位号来进行抽奖游戏,根据不同的号码来决定奖项的大小。使用 switch 语句编写 Java 程序来完成奖项分配,其实现代码如下。

public static void main(String[] args) {
    System.out.println("请输入座位号码:");
    Scanner sc = new Scanner(System.in);
    int num = sc.nextInt();
    switch (num) {
    case 8:
        System.out.println("恭喜你,获得了三等奖!");
        break;
    case 88:
        System.out.println("恭喜你,获得了二等奖!");
        break;
    case 888:
        System.out.println("恭喜你,获得了一等奖!");
        break;
    default:
        System.out.println("谢谢参与!");
        break;
    }
}

switch 也可嵌套使用,这里不进行赘述。

3.4 if 与 switch 的取舍

从泛用性的角度来说,if 结构无疑比 switch 结构更加灵活,因此,泛用性和实用性更强。

从运行速度角度来说,在对同一个变量的不同值作条件判断时,既可以使用 switch 语句,也可以使用 if 语句。使用 switch 语句的效率更高一些,尤其是判断的分支越多,越明显。

一般情况下,对于判断条件较少的,可以使用 if 条件语句,但是在实现一些多条件的判断中,最好使用 switch 语句。