本文最后更新于:2023年12月10日 16:49:22
本文中使用到的工具是Intellij IDEA和JDK 8,需要安装两款工具的请查看这两篇教程:点我查看安装JDK8/11/17教程、点我查看安装Intellij IDEA教程。
前面我们写过的代码,都是在main
方法中自上到下按顺序执行的,举一个代码栗子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public class MyWatermelonDemo1 { public static void main(String[] args) { int price = 2; int weight = 10; int totalPrice = price * weight; System.out.println("西瓜的价格是: " + totalPrice + "元"); } }
|
这段代码就是先定义西瓜的单价、再定义西瓜的重量,然后计算西瓜的价格,最后对价格进行输出。像这样代码从上到下执行的结构就是顺序结构。
程序一共有三种控制结构:顺序结构、选择结构和循环结构。其中选择结构是根据条件判定的结果,选择执行不同的代码,例如:红灯停,绿灯行。判断条件就是交通信号灯的状态。
Java也有选择结构,并且有多种类型的条件判断语句:单分支的if
语句、双分支的if-else
语句、多分支的if-else if-else
语句、if
嵌套语句和switch
语句。
一、单分支if语句
单分支if
语句的语法如下:
其中条件表达式的计算结果必须是boolean
类型。如果条件表达式的计算结果是true
,那么就会执行if
内部的代码;如果表达式为false
,此时就会跳过if
代码块(也就是if
内部代码不执行),概念图如下:
.png)
我们可以在if
代码块中可以编写多个执行语句。
以下是if
的使用案例:
案例:之前长春下了大暴雪,气温骤降,我想在某宝上买几双棉袜子,假设每双袜子4元,请确保输入的数字大于0再计算购买价格。
分析:解题的关键在于要保证输入的数字要大于0,因此要判断输入的数字是否大于0,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.util.Scanner;
public class IfDemo1 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入袜子的数量"); int count = scanner.nextInt(); double totalPrice = 0.0; double price = 4; if (count > 0) { totalPrice = count * price; System.out.println("购买了" + count + "双袜子, 价格是" + totalPrice + "元"); } } }
|
运行结果:

案例:输入一个数字,如果能被10整除,则输出内容为:xx能被10整除。如果能被15整除,则输出内容为:xx能被15整除。
解决本题的关键点在于被10整除和被15整除的条件怎么计算。其实前面我们学过取余运算符,如果数值number
能被10整除,那么可以写成number % 10 == 0
;如果数值number
能被15整除,那么可以写成number % 15 == 0
。这两个布尔表达式可以写入到两个if
语句中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import java.util.Scanner;
public class IfDemo2 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入数字: "); int number = scanner.nextInt();
if (number % 10 == 0) { System.out.println(number + "能被10整除"); }
if (number % 15 == 0) { System.out.println(number + "能被15整除"); } } }
|
输入不同的数字以后,会得到如下的运行结果:

案例:输入两个整数,如果输入的第一个数字比第二个数字大,那么执行两数交换,并将交换结果输出。否则不交换,正常输出两个数
本题的条件表达式是输入的两个数字的比较,无论数字大小比较结果如何,都需要将结果进行输出,我们可以将输出语句放到if
语句后面执行。
两数交换有多种方式,较为稳妥的方式是再定义一个临时变量,用这个临时变量来接收第一个变量值,然后第二个变量值赋值给第一个变量,最后将临时变量的值赋值给第二个变量。
以下是示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import java.util.Scanner;
public class IfDemo3 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入两个整数"); int number1 = scanner.nextInt(); int number2 = scanner.nextInt(); int temp = 0; if (number1 > number2) { temp = number1; number1 = number2; number2 = temp; } System.out.println("第一个数是: " + number1 + ", 第二个数是: " + number2); } }
|
运行结果:

当然,除了上述方式能实现两数交换,还有其他的方式。
方式一:使用加减法进行交换(推荐使用整数,浮点数不推荐,因为浮点数计算时会出现误差)
1 2 3 4 5
| int number1 = 3; int number2 = 2; number1 = number1 + number2; number2 = number1 - number2; number1 = number1 - number2;
|
方式二:使用位运算符进行交换(推荐使用整数,此处涉及到二进制异或运算,异或运算可以查看这篇文章:入门篇-其之六-Java运算符(中)第四部分-位运算符)
1 2 3 4 5
| int number1 = 3; int number2 = 2; number1 = number1 ^ number2; number2 = number1 ^ number2; number1 = number1 ^ number2;
|
当然,上述三种方式我个人最推荐的还是第一种定义临时变量的方式,这种方式对处理浮点类型的数进行交换很友好,如果使用了下面两种方式的话,可能会在计算过程中出现精度损失的问题。后两种方式的好处是不需要定义第三个变量,只需要进行一系列运算即可完成整数值的交换。
二、if-else双分支语句
前面讲过的单分支if
语句只有在布尔表达式为true
的时候执行其内部的内容,但是如果在布尔表达式为false
的时候不会做任何事情。为了解决上述问题,Java为我们提供了if-else
双分支语句。以下是双分支if-else
语句代码结构:
1 2 3 4 5
| if (条件表达式) { 执行代码1... } else { 执行代码2... }
|
如果条件表达式的值是true
,那么就执行if
内部的语句,如果条件表达式为false
,此时就进入else
代码块。执行流程图如下:

案例:我们还是以上述买袜子为例,最近双十一打折,如果买了10双及以上袜子,此时每双袜子打八折优惠,否则打九折优惠(袜子的价格假设是4元/双)。
题目中的条件表达式在于要买的袜子数量是否大于等于10,如果是,价格打8折,否则打9折,使用刚刚讲到的if-else
语句即可搞定。
当然,这道题中还有一个隐藏的细节需要我们处理:输入袜子的数量需要大于0,否则判定为无效,这个可以使用单分支if
语句就可以搞定。
以下是示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import java.util.Scanner;
public class IfDemo4 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入要购买的袜子数量"); int count = scanner.nextInt(); double price = 4; double totalPrice = 0.0; if (count > 0) { if (count >= 10) { totalPrice = price * 0.8 * count; } else { totalPrice = price * 0.9 * count; } } System.out.println("购买" + count + "双袜子,双十一期间购买价格是" + totalPrice + "元"); } }
|
运行结果(可能会出现浮点数计算不准确的情况,属于正常现象):

三、if-else if-else多分支语句
双分支的if-else
语句对于条件表达式为true
和false
的时候比较适用,但是如果对于一个问题而言,此时经过分析可能存在多个条件表达式时,if-else
语句并不能很好地完成任务,此时Java为我们提供了另一种分支语句:if-else if-else
语句,其语法格式如下:
1 2 3 4 5 6 7 8 9 10 11 12
| if (条件表达式1) { 执行代码1... } else if (条件表达式2) { 执行代码2... } else if (条件表达式3) { 执行代码3... } ... else if (条件表达式n) { 执行代码n... } else { 不符合上述所有条件表达式时执行else代码... }
|
以上述语法格式为例,其执行顺序为:
- 如果条件表达式1的结果为
true
,那么执行代码1,如果结果是false
,此时就会跳转到第一个else if
。
- 如果条件表达式2的结果是
true
,那么执行代码2,如果结果是false
,那么就会跳转到第二个else if
。
- 如果条件表达式3的结果是
true
,那么执行代码3,如果结果是false
,那么就会跳转到下一个else if
,依次类推。
- 当上述所有的条件表达式都不满足(即结果全部是
false
)时,就会执行else
中的语句。
多分支的if-else if-else
语句中,你可以写任意个else if
,每个else if
需要写上条件表达式。
当然,最后的else
也是可选的,if
和else-if
搭配使用也是可以的。以下是执行流程图:

案例:已知长春的地铁/轻轨票价标准如下
- 0-7公里(含7公里),票价2元;
- 7-13公里(含13公里),票价3元;
- 13-19公里(含19公里),票价4元;
- 19-27公里(含27公里),票价5元;
- 27-35公里(含35公里),票价6元;
- 35公里以上每增加10公里,增加1元
假设从1号线红嘴子地铁站到8号线广通路轻轨站的距离是31.4公里,从2号线汽车公园地铁站到2号线东方广场地铁站的距离是20.5公里,从4号线长春站北轻轨站到4号线天工路轻轨站的距离是16.3公里。
输入上述里程,利用程序计算出乘坐轨道交通所需要的票价。
上述题目中出现了多个条件判断,每个条件判断执行内容都不相同,使用多分支语句if-else if-else
语句比较合适。题目中有一个隐藏条件,输入里程数不能为负数,当然这个条件也直接写入条件判断即可。
如果乘坐轨道交通的里程超过35公里以后,每增加10公里,增加1元。例如:乘坐45公里就要在35公里对应的票价6元的基础上再增加1元,当然,55公里、65公里依次类推。假设称作里程为44.9公里,此时收费标准仍为35公里的票价。
针对上述问题,我们可以在代码中进一步呈现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import java.util.Scanner;
public class ElseIfDemo1 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入里程数: "); double distance = scanner.nextDouble(); int price = 0; if (distance <= 0) { System.out.println("无效里程"); } else if (distance > 0 && distance <= 7) { price = 2; } else if (distance > 7 && distance <= 13) { price = 3; } else if (distance > 13 && distance <= 19) { price = 4; } else if (distance > 19 && distance <= 27) { price = 5; } else if (distance > 27 && distance <= 35) { price = 6; } else { price = 6; int additionalDistance = (int) (distance - 35); price = price + additionalDistance / 10; } System.out.println("乘坐长春轨道交通里程" + distance + "公里,票价" + price + "元"); } }
|
运行结果如下:

四、if的嵌套使用
正如标题所讲,if
语句可以嵌套使用。举个栗子:在main
方法中,假设已经存在了一个if-else
语句,那么在这个if
代码块或者else
代码块还可以存在条件判断语句,下面就是其中一种if
的嵌套使用方式(事实上它可以if
代码块可以进行多种组合嵌套使用):
1 2 3 4 5 6 7 8 9 10 11 12 13
| if (条件表达式1) { if (条件表达式2) { 执行代码1... } else { 执行代码2... } } else { if (条件表达式3) { 执行代码3... } else { 执行代码4... } }
|
它的执行流程如下:
- 如果条件表达式1的执行结果是
true
,进入条件表达式2,如果条件表达式2执行结果是true
,此时执行代码1。
- 如果条件表达式1的执行结果是
true
,进入条件表达式2,如果条件表达式2执行结果是false
,此时执行代码2。
- 如果条件表达式1的执行结果是
false
,进入条件表达式3,如果条件表达式3执行结果是true
,此时执行代码3。
- 如果条件表达式1的执行结果是
false
,进入条件表达式3,如果条件表达式3执行结果是false
,此时执行代码4。
执行流程图如下所示:

日常写代码的过程中,尽量保证代码嵌套的层数不超过两层。
案例:输入三个数,要求输出是按照从大到小进行排列。例如,输入三个数为20、30、10,输出结果为30、20、10
- 第一层条件:比较第一个数和第二个数。
- 第二层条件:比较第二个数和第三个数。
- 第三层条件:比较第一个数和第三个数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import java.util.Scanner;
public class IfDemo5 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入三个整数: "); int number1 = scanner.nextInt(); int number2 = scanner.nextInt(); int number3 = scanner.nextInt(); if (number1 > number2) { if (number2 > number3) { System.out.println("三个数从大到小的排序是: " + number1 + " " + number2 + " " + number3); } else { if (number1 > number3) { System.out.println("三个数从大到小的排序是: " + number1 + " " + number3 + " " + number2); } else { System.out.println("三个数从大到小的排序是: " + number3 + " " + number1 + " " + number2); } } } else { if (number2 < number3) { System.out.println("三个数从大到小的排序是: " + number3 + " " + number2 + " " + number1); } else { if (number1 > number3) { System.out.println("三个数从大到小的排序是: " + number2 + " " + number3 + " " + number1); } else { System.out.println("三个数从大到小的排序是: " + number2 + " " + number1 + " " + number3); } } } } }
|
运行结果:

虽然运行结果符合我们的预期,但是我只能说:这样的代码写的非常糟糕!!!这段代码中if
的嵌套层数达到了三层,事实上if
嵌套两层以上可读性就大打折扣了。
我们可以使用Java数组、循环和数组方法对此问题做进一步处理(小白可以跳过这一部分)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.util.Arrays; import java.util.Scanner;
public class IfDemo6 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入三个数字: "); Integer[] array = new Integer[3]; for (int i = 0; i < array.length; i++) { array[i] = scanner.nextInt(); } Arrays.sort(array, (o1, o2) -> o2 - o1); System.out.println("三个数从大到小的排序是: " + array[0] + " " + array[1] + " " + array[2]); } }
|
运行结果:

五、switch语句
if-else if-else
多分支语句可以用于多个条件表达式的判断,我们可以写非常多的else if
,然而过多的else if
可能会导致代码的可读性变差。
Java为我们提供了swtich
语句在一定程度上可以简化多条件分支。以下是switch
的语法结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| switch (表达式) { case 值1: 执行代码1... break; case 值2: 执行代码2... case 值3: 执行代码3... break; ... case 值n: 执行代码n... break; default: 上述条件都不适用执行代码... }
|
1. switch
语句中表达式的计算结果、值1、值2、…、值n的数据类型必须要保持一致。支持的数据类型包括:**byte
、short
、int
、char
、字符串类型String
(JDK 7新特性)、枚举类型**(后续会讲到,JDK 7新特性)。
2. 如果表达式的计算结果和case
中某个值相等时,就会执行这个case
内的代码。
3. switch
语句中的default
是可选的,它的作用是当表达式的计算结果和所有case
的值都不相等时才会执行default
语句,如果default
语句不存在时,所有的case
对应的值和判定值都不相等时,跳出switch
语句。
4. break
的作用是跳出switch
语句(break
关键字还会在循环中遇到),在每一个case
对应的代码块后面写上break
是个好习惯。
如果case
中不加break
,此时switch
语句会出现穿透性,即当某一个case
执行完成后,它会继续执行下面其他的case
。以下是一个是否使用break
的案例:
案例:输入数字1~7,使用switch
语句输出当前日期(假设7代表星期日)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import java.util.Scanner;
public class SwitchDemo1 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入星期数(1~7), 7表示星期日"); int number = scanner.nextInt(); switch (number) { case 1: String monday = "星期一"; System.out.println("今天是" + monday); case 2: String tuesday = "星期二"; System.out.println("今天是" + tuesday); case 3: String wednesday = "星期三"; System.out.println("今天是" + wednesday); case 4: String thursday = "星期四"; System.out.println("今天是" + thursday); case 5: String friday = "星期五"; System.out.println("今天是" + friday); case 6: String saturday = "星期六"; System.out.println("今天是" + saturday); case 7: String sunday = "星期日"; System.out.println("今天是" + sunday); default: System.out.println("无效日期"); } } }
|
运行结果:

很明显,输入数字3的时候,由于没有break
,当执行case 3
内部代码以后,它会向下执行其他case
中的代码,直至default
内的代码执行完毕为止。并且这段代码还有可以进一步修改的空间,以下是加入break
并进行简化的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import java.util.Scanner;
public class SwitchDemo2 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入星期数(1~7), 7表示星期日"); int number = scanner.nextInt(); String weekday; switch (number) { case 1: weekday = "星期一"; break; case 2: weekday = "星期二"; break; case 3: weekday = "星期三"; break; case 4: weekday = "星期四"; break; case 5: weekday = "星期五"; break; case 6: weekday = "星期六"; break; case 7: weekday = "星期日"; break; default: weekday = "无效星期"; } System.out.println("今天是" + weekday); } }
|
运行结果:

从上述结果可以看出,使用break
以后,就可以阻断switch
穿透性。
switch
语句执行流程如下图所示(每个case
都带上break
语句):

在了解了switch
语句的基础上,我们再来讲解一个switch
语句和if-else
语句结合使用的案例:
案例:输入年份和月份,输出格式如下:xxxx年xx月有xx天。
常识:1、3、5、7、8、10、12恒定是31天;4、6、9、11恒定为30天。这几个月份我们可以利用switch
的穿透性替换掉多条件的else if
判断。
需要额外考虑的是:2月份的天数需要考虑年份是闰年还是平年,闰年能被400整除,例如:2000年,1600年是闰年,1900年就不是闰年。此外,如果不能被100整除,而能被4整除的也是闰年,例如:2020,2016,2004,2008年都是闰年。
结合上述分析,我们可以使用代码进一步复现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| import java.util.Scanner;
public class SwitchDemo3 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入年份: "); int year = scanner.nextInt(); System.out.print("请输入月份: "); int month = scanner.nextInt(); int day = 0; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: day = 31; break; case 4: case 6: case 9: case 11: day = 30; break; case 2: if (year % 400 == 0) { day = 29; } else if (year % 4 == 0 && year % 100 != 0) { day = 28; } break; default: System.out.println("无效的月份"); } System.out.println(year + "年" + month + "月有" + day + "天"); } }
|
运行结果:

以我个人的开发经验来看,使用switch
语句的频率要比使用if
语句要少很多,二者的执行效率基本上差不太多。
if
可以编写更加灵活的条件表达式。比如:判断某个整数在[10, 20]
区间内,此时使用if
条件表达式可以写成if (number >= 10 && number <= 20)
,如果使用switch
解决此问题会让代码变得更加复杂(因为你要写很多个case
进行比较)。
switch
更擅长特定类型的值进行比较。以上面根据某年某月求当前月份由多少天为例,事实上完全使用if
语句实现,只不过我们需要写成:
使用前面案例对应的switch
代码,和if
语句对比,个人觉得可读性变高:
因此,使用if
语句还是switch
语句还是得根据具体的代码场景而决定。
六、《阿里巴巴Java开发手册》关于条件判断语句的相关规范
1. 【强制】在一个switch
块内,每个case
要么通过continue/break/return
等来终止,要么注释说明程序将继续执行到哪一个case
为止;在一个switch
块内,都必须包含一个default
语句并且放在最后,即使它什么代码也没有。
说明:注意break
是退出switch
语句块,而return
是退出方法体。
2. 【强制】当switch
括号内的变量类型为String
并且此变量为外部参数时,必须先进行null
判断。
反例:如下的代码输出内容是什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class SwitchString { public static void main(String[] args) { method(null); } public static void method(String param) { switch (param) { case "sth": System.out.println("it's sth"); break; case "null": System.out.println("it's null"); break; default: System.out.println("default"); } } }
|
3. 【强制】在if/else/for/while/do
语句中必须使用大括号。
说明:即使只有一行代码,禁止不采用大括号的编码方式:if (条件表达式) statements;
,上述代码需改成如下格式:
1 2 3
| if (条件表达式) { statements; }
|
4. 【推荐】表达异常的分支时,少用if-else
方式,这种方式可以改写成:
1 2 3 4 5
| if (condition) { ... return obj; }
|
说明:如果非使用if()...else if()...else...
方式表达逻辑,避免后续代码维护困难,请勿超过 3 层。
正例:超过 3 层的if-else
的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现,其中卫语句示例如下(不了解卫语句是什么的小伙伴可以参考这篇文章:点我查看):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public void findBoyfriend (Man man){ if (man.isUgly()) { System.out.println("本姑娘是外貌协会的资深会员"); return; } if (man.isPoor()) { System.out.println("贫贱夫妻百事哀"); return; } if (man.isBadTemper()) { System.out.println("银河有多远,你就给我滚多远"); return; } System.out.println("可以先交往一段时间看看"); }
|
5. 【推荐】避免采用取反逻辑运算符。
说明:取反逻辑不利于快速理解,并且取反逻辑写法必然存在对应的正向逻辑写法。
正例:使用if (x < 628)
来表达 x 小于 628。
反例:使用if (!(x >= 628))
来表达 x 小于 628。
七、知识点总结
流程控制之条件判断知识点总结如下图所示:
如需高清大图,请点击右侧链接下载文件:点我下载
