4.2 分支结构 4.2.1 if条件语句

4.2 分支结构

Java提供了两种常见的分支控制结构:if语句和switch语句,其中

  • if语句使用**布尔表达式布尔值**作为分支条件来进行分支控制;
  • switch语句则用于对多个整型值进行匹配,从而实现分支控制。

4.2.1 if条件语句

if语句的三种形式

if语句使用布尔表达式或布尔值作为分支条件来进行分支控制。if语句有如下三种形式。
第一种形式:

1
2
3
4
if(logic expression)
{
statement
}

第二种形式:

1
2
3
4
5
if (logic expression){
statement
} else {
statement
}

第三种形式:

1
2
3
4
5
6
7
8
9
10
11
12
if (logic expression){
statement
}
else if(logic expression){
statement
}
//可以有零个或多个else if语句
...
//最后的else语句也可以省略
else{
statement
}

在上面if语句的三种形式中,放在if之后括号里的只能是一个逻辑表达式,即这个表达式的返回值只能是truefalse。第二种形式和第三种形式是相通的,如果第三种形式中else if块不出现,就变成了第二种形式。

条件执行体

在上面的条件语句中,if(logic expression)else if(logic expression)else花括号括起来的多行代码被称为代码块,一个代码块通常被当成一个整体来执行(除非运行过程中遇到returnbreakcontinue等关键字,或者遇到了异常),因此这个代码块也被称为条件执行体。例如如下程序。

1
2
3
4
5
6
7
8
int age = 30;
if (age > 20)
// 只有当age > 20时,下面花括号括起来的语句块才会执行
// 花括号括起来的语句是一个整体,要么一起执行,要么一起不会执行
{
System.out.println("年龄已经大于20岁了");
System.out.println("20岁以上的人应该学会承担责任...");
}

条件执行体只有一条语句的话可省略花括号

如果if(logic expression)else if(logic expression)else后的代码块只有一行语句时,则可以省略花括号,因为单行语句本身就是一个整体,无须用花括号来把它们定义成一个整体。下面代码完全可以正常执行:

1
2
3
4
5
6
7
8
9
// 定义变量a ,并为其赋值
int a = 5;
if (a > 4)
// 如果a>4,执行下面的执行体,只有一行代码作为代码块
System.out.println("a大于4");
else
// 否则,执行下面的执行体,只有一行代码作为代码块
System.out.println("a不大于4");

建议不要省略条件执行体的花括号

通常建议不要省略ifelseelse if后执行体的花括号,即使条件执行体只有一行代码,也保留花括号会有更好的可读性,而且保留花括号会减少发生错误的可能。例如如下代码,则不能正常执行:

1
2
3
4
5
6
7
8
9
10
11
// 定义变量b ,并为其赋值
int b = 5;
if (b > 4)
// 如果b>4,执行下面的执行体,只有一行代码作为代码块
System.out.println("b大于4");
else
// 否则,执行下面的执行体,只有一行代码作为代码块
b--;
// 对于下面代码而言,它已经不再是条件执行体的一部分,因此总会执行。
System.out.println("b不大于4");

上面的

1
System.out.println("b不大于4");

这行代码总会执行,因为这行代码不属于else后的条件执行体,else后的条件执行体就是b--;这行代码。
ifelseelse if后的条件执行体要么是一个花括号括起来的代码块,则这个代码块整体作为条件执行体;要么是以分号为结束符的一行语句,甚至可能是一个空语句(空语句是一个分号),那么就只是这条语句作为条件执行体。**如果省略了if条件后条件执行体的花括号,那么if条件只控制到紧跟该条件语句的第一个分号处**。
如果if后有多条语句作为条件执行体,若省略了这个条件执行体的花括号,则会引起编译错误看下面代码

1
2
3
4
5
6
7
8
9
10
11
12
// 定义变量c ,并为其赋值
int c = 5;
if (c > 4)
// 如果b>4,执行下面的执行体,将只有c--;一行代码为条件体
c--;
// 下面是一行普通代码,不属于条件体
System.out.println("c大于4");
// 此处的else将没有if语句,因此编译出错。
else
// 否则,执行下面的执行体,只有一行代码作为代码块
System.out.println("c不大于4");

在上面代码中,因为if后的条件执行体省略了花括号,则系统只把c-;行代码作为条件执行体当c-;语句结束后,if语句也就结束了。后面的:

1
System.out.println("c大于4");

这行代码已经是一行普通代码了,不再属于条件执行体,从而导致**else语句没有匹配的if语句**,从而引起编译错误。

优先把包含范围小的条件放在前面处理

对于if语句,还有一个很容易出现的逻辑错误,这个逻辑错误并不属于语法问题,但引起错误的可能性更大。看下面程序。

1
2
3
4
5
6
7
8
9
10
11
12
public class IfErrorTest {
public static void main(String[] args) {
int age = 45;
if (age > 20) {
System.out.println("青年人");
} else if (age > 40) {
System.out.println("中年人");
} else if (age > 60) {
System.out.println("老年人");
}
}
}

表面上看起来,上面的程序没有任何问题:人的年龄大于20岁是青年人,年龄大于40岁是中年人,年龄大于60岁是老年人。但运行上面程序,发现打印结果是:青年人,而正确的情况是:45岁是中年人;

else的隐含条件是对前面条件取反

对于任何的if else语句,表面上看起来else后没有任何条件,或者else if后只有一个条件,但这不是真相:
因为else的含义是“否则”,所以else本身就是一个条件!else的隐含条件是对前面条件取反。因此,上面代码实际上可改写为如下形式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class IfErrorTest2 {
public static void main(String[] args) {
int age = 45;
if (age > 20) {
System.out.println("青年人");
}
// 在原本的if条件中增加了else的隐含条件
if (age > 40 && !(age > 20)) {
System.out.println("中年人");
}
// 在原本的if条件中增加了else的隐含条件
if (age > 60 && !(age > 20) && !(age > 40 && !(age > 20))) {
System.out.println("老年人");
}
}
}

省略…

正确的写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
public class IfCorrectTest {
public static void main(String[] args) {
int age = 45;
if (age > 60) {
System.out.println("老年人");
} else if (age > 40) {
System.out.println("中年人");
} else if (age > 20) {
System.out.println("青年人");
}
}
}

如果每次都去计算if条件和else条件的交集也是一件非常烦琐的事情,为了避免出现上面的错误,在使用if...else语句时有一条基本规则:总是优先把包含范围小的条件放在前面处理,例如:age>60age>20两个条件,明显age>60的范围更小,所以应该先处理age>60的情况。
注意:使用if...else语句时,一定要先处理包含范围更小的情况