JavaSE - 流程控制
本节学习目标:
- 熟悉并掌握复合语句的使用方式;
- 熟悉并掌握条件语句的使用方式;
- 熟悉并掌握循环语句的使用方式;
- 熟悉并掌握循环控制语句的使用方式;
1. 流程控制概述
流程控制对于任何一门编程语言来说都是至关重要的,它提供了控制程序步骤的基本手段。
流程控制语句是用控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。
流程控制语句根据功能不同分为四类:
- 复合语句;
- 条件语句;
- 循环语句;
- 循环控制语句。
2. 复合语句
与C语言及其他语言相同,Java语言的复合语句是以整个块区为单位的语句,所以又称为块语句。复合语句由大括号({}
)包围。
在之前的学习中,类体就是以“{}
”作为开始与结束的标记,方法体也是如此。复合语句中的每条语句都是从上到下被执行。
- 在方法体中,代码块中的语句从上到下被执行,要注意局部变量的使用范围。
编写代码进行测试:
public class CompoundSentence {
public static void main(String[] args) {
int a = 10;
{
int b = 6;
System.out.println("b=" + b);
{
System.out.println("a+b=" + (a + b));
}
}
System.out.println("Hello World!");
}
}
运行结果:
b=6
a+b=16
Hello World!
- 在类体中,使用代码块有两种情况:
- 静态代码块:由关键字
static
修饰的代码块。此代码块中的代码仅会在类被加载时执行一次,主要用来进行初始化类变量(被static
关键字修饰的变量)。 - 非静态代码块:此代码块中的代码会在创建此类的对象时执行,主要用来初始化实例变量。
- 静态代码块:由关键字
编写代码进行测试:
public class Person {
{
System.out.println("非静态代码块执行了!");
}
static {
System.out.println("静态代码块执行了!");
}
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
Person p3 = new Person();
}
}
测试结果:
静态代码块执行了!
非静态代码块执行了!
非静态代码块执行了!
非静态代码块执行了!
3. 条件语句
条件语句可根据不同的条件执行不同的语句。
条件语句分为两种:if-else
条件分支语句和switch-case
多分支语句。
3.1 if-else 条件分支语句
在上节学习条件运算符(?:
)时就已经简单了解了条件分支语句。
if
简单分支语句
语法如下:
if (布尔表达式) {
语句1;
语句2;
...
}
如果布尔表达式的值为真,则执行**if
语句块**内的语句,否则不执行。
if-else
语句
语法如下:
if (布尔表达式) {
语句;
...
} else {
语句;
...
}
如果布尔表达式的值为真,则执行**if
语句块内的语句,否则执行else
语句块**内的语句。
if...else if
多分支语句
语法如下:
if (布尔表达式1) {
语句;
...
} else if (布尔表达式2) {
语句;
...
}
...
else if (布尔表达式N) {
语句;
...
} else {
语句;
...
}
此时会从上到下依次计算布尔表达式,一旦有一个布尔表达式的值为真,则执行此布尔表达式所在的块的语句,下面的语句都不会执行。
如果所有布尔表达式都为假则执行else
语句块内的语句(如果没有else
语句块则不会执行任何语句块内的语句)。
编写代码进行测试:
public class ConditionalSentenceIf {
public static void main(String[] args) {
int a = 5;
if (a == 4) {
System.out.println("Hello World!");
} else {
System.out.println("Do Hello World!");
}
char b = 'C';
if (b == 'A') {
System.out.println("b=A");
} else if (b == 'B') {
System.out.println("b=B");
} else if (b == 'C') {
System.out.println("b=C");
}
}
}
运行结果:
Do Hello World!
b=C
3.2 switch-case 多分支语句
if...else if
多分支语句如果else if
代码块有很多个,那么编写的代码会非常笨重,显得冗余杂乱,影响阅读;
在Java中可以使用switch-case
多分支语句来替代:
switch (表达式) {
case 常量1: {
语句块;
[break;]
}
case 常量2: {
语句块;
[break;]
}
...
case 常量N: {
语句块;
[break;]
}
default: {
语句块;
[break;]
}
}
switch
语句中表达式的值必须为整型,字符型、枚举类型(Java5新增)和字符串(Java7新增),常量1~N必须也为整型,字符型或字符串。
switch
语句首先会计算表达式的值,如果表达式的值和某个case
后的常量值相同,则执行该case
以及之后的case
中的语句块。直到遇到break
语句为止。
如果表达式的值和任何case
后的常量值都不相同,则会执行default
语句块中的语句(如果不存在default
块则任何语句都不会执行)。
编写代码进行测试:
public class ConditionalSentenceSwitch {
public static void main(String[] args) {
int a = 3;
switch (a + 1) {
case 3: {
System.out.println("语句块3被执行");
}
case 4: {
System.out.println("语句块4被执行");
}
case 5: {
System.out.println("语句块5被执行");
break;
}
case 6: {
System.out.println("语句块6被执行");
}
}
String str = "123";
switch (str) {
case "234": {
System.out.println("语句块234被执行");
}
case "345": {
System.out.println("语句块345被执行");
}
default: {
System.out.println("语句块default被执行");
}
}
}
}
运行结果:
语句块4被执行
语句块5被执行
语句块default被执行
3.3 使用 Scanner 类从键盘输入数据
我们想要使用键盘输入数据到程序中,需要使用Scanner
类。Scanner
类提供了很多输入方法:
nextByte
:从键盘输入byte
类型数据;nextShort
:从键盘输入short
类型数据;nextInt
:从键盘输入int
类型数据;nextLong
:从键盘输入long
类型数据;nextFloat
:从键盘输入float
类型数据:nextDouble
:从键盘输入double
类型数据;nextBoolean
:从键盘输入boolean
类型数据;nextLine
:从键盘输入字符串类型数据;
这些输入方法只能输入对应类型的数据(也能输入可以转换为当前类型数据的其他类型数据),否则将报错。
Scanner
类的使用方法:使用构造方法创建Scanner
对象,并传入System.in
流作为参数:
Scanner scanner = new Scanner(System.in);
编写代码进行测试:
import java.util.Scanner;
public class ScannerTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
System.out.println("输入的a的值为" + a);
scanner.close(); // 建议scanner使用完毕后调用close方法关闭
}
}
输入:4
,运行结果:
4. 循环语句
循环语句就是在满足一定条件下反复执行某一个操作。在Java中提供了三种常用的循环语句,分别是while
循环语句、do-while
循环语句和for
循环语句。
4.1 while 循环语句
while
循环语句使用一个布尔表达式控制是否要继续反复执行语句块:
while (布尔表达式) {
语句块;
}
计算布尔表达式的值,当布尔表达式的值为真时,执行语句块中的语句。当执行完语句块中的语句后,重新计算布尔表达式的值,循环执行。
直到布尔表达式的值为假,退出循环。
编写代码进行测试:
public class LoopSentenceWhile {
public static void main(String[] args) {
int x = 1;
while (x <= 5) {
System.out.println("x=" + x);
x++;
}
}
}
运行结果:
x=1
x=2
x=3
x=4
x=5
4.2 do-while 循环语句
do-while
循环语句和while
循环语句类似,它们之间的区别是while
循环语句需要先判断条件是否成立,而do-while
循环语句需要先执行一次语句块再判断条件是否成立。
也就是说do-while
循环语句的语句块至少要被执行一次。语法如下:
do {
语句块;
} while (布尔表达式);
使用4.1章节的代码进行测试:
public class LoopSentenceDoWhile {
public static void main(String[] args) {
int x = 1;
do {
System.out.println("x=" + x);
x++;
} while (x <= 5);
}
}
运行结果:
x=1
x=2
x=3
x=4
x=5
4.3 for 循环语句
for
循环是Java程序设计中最有用的循环语句之一。一个for循环可以用来重复执行某条语句,直到某个条件得到满足。在Java5以后新增了foreach语法。
for
语句的语法如下:
for (表达式1, 表达式2, 表达式3) {
语句块;
}
- 表达式1:初始化表达式,负责完成变量的初始化,进行for循环时只会执行一次;
- 表达式2:布尔表达式,用于指定循环条件,进行for循环时每次循环前执行一次;
- 表达式3:循环后操作表达式,负责修整变量,改变循环条件,进行for循环时每次循环后执行一次。
进行for
循环时,首先执行表达式1,完成某一变量的初始化工作;然后计算表达式2,如果值为真,执行语句块,进行一次循环。语句块执行完后立即执行表达式3,
这部分通常是增加或减少循环控制变量的一个表达式。表达式3执行完后一轮循环结束。第二轮循环再从计算表达式2开始,如果值为真则继续循环,如果值为假则跳出整个for
循环语句。
编写语句进行测试:
public class LoopSentenceFor {
public static void main(String[] args) {
for (int x = 0; x < 5; x++) {
System.out.println("for循环执行了" + x + "次");
}
}
}
运行结果:
for循环执行了0次
for循环执行了1次
for循环执行了2次
for循环执行了3次
for循环执行了4次
foreach语句是for
循环的特殊简化版本,不能完全取代for语句,但任何foreach语句都能改写为for
语句。
foreach并不是一个关键字,习惯上将这种特殊的for语句格式称为foreach语句。它在遍历数组等方面为程序员提供了很大的方便。
语法如下:
for (元素变量: 数组对象) {
语句块;
}
foreach语句中的元素变量不需对其进行初始化,使用元素变量来遍历数组对象,对数据对象的每个元素都遍历一遍,直到每个元素都遍历一次后循环结束。
编写代码进行测试:
public class LoopSentenceForeach {
public static void main(String[] args) {
int[] list = {1, 2, 3, 4, 5};
for (int x: list) {
System.out.println("x=" + x);
}
}
}
运行结果:
x=1
x=2
x=3
x=4
x=5
5. 循环控制语句
Java提供了两个关键字:break
和continue
来控制循环的跳转。
break
语句跳出整个循环;continue
语句跳出本次循环。
如果循环语句的循环条件永远为真(比如布尔表达式直接写
true
),那么循环将会一直执行下去,这种循环被称为“死循环”。
不仅不能让程序按顺序依次执行下去,而且还会消耗系统资源,严重者可使程序崩溃。
编写代码的过程中必须要认真检查循环条件,防止“死循环”出现。
5.1 break 语句
使用break
语句可以跳出switch
结构:
public class BreakSwitch {
public static void main(String[] args) {
int x = 1;
switch (x) {
case 1: {
System.out.println("执行了case1");
// 此处没有break,则会执行之后的case
}
case 2: {
System.out.println("执行了case2");
break; // break跳出switch后,之后的case不会再执行了
}
case 3: {
System.out.println("执行了case3");
}
}
}
}
运行结果:
执行了case1
执行了case2
使用break
语句还可以跳出循环:
public class BreakLoop {
public static void main(String[] args) {
int a = 1;
while (a < 5) {
if (a == 3) {
break; // 当a的值自增到3时跳出while循环
}
System.out.println("执行了while循环" + a + "次");
a++;
}
int b = 1;
do {
System.out.println("执行了do-while循环" + b + "次");
if (b == 3) {
break; // 当b的值自增到3时跳出do-while循环
}
b++;
} while (b < 5);
for (int c = 1; c < 5; c++) {
System.out.println("执行了for循环" + c + "次");
if (c == 3) {
break; // 当c的值自增到3时跳出for循环
}
}
}
}
运行结果:
执行了while循环1次
执行了while循环2次
执行了do-while循环1次
执行了do-while循环2次
执行了do-while循环3次
执行了for循环1次
执行了for循环2次
执行了for循环3次
- 如果循环嵌套循环,
break
语句只能跳出语句所在的循环体,外层循环无法跳出。
如果想让break
跳出外层循环,Java提供了标签的功能,语法如下:
标签名: 循环体 {
break 标签名;
}
编写代码进行测试:
public class BreakExternalLoop {
public static void main(String[] args) {
xLoop: for (int x = 0; x < 5; x++) {
for (int y = 0; y < 5; y++) {
if (x == 3) {
break xLoop;
}
System.out.print("y=" + y);
}
System.out.println("x=" + x);
}
}
}
运行结果:
y=0y=1y=2y=3y=4x=0
y=0y=1y=2y=3y=4x=1
y=0y=1y=2y=3y=4x=2
可以看到x的值自增到3时,if语句成立,执行break语句,直接跳出指定的外层循环体了。
5.2 continue 语句
continue
语句是针对break
语句的补充。continue
不是立即跳出循环体,而是跳过本次循环结束前的语句,回到循环的条件测试部分,重新开始执行循环。
编写代码进行测试:
public class ContinueLoop {
public static void main(String[] args) {
int a = 0;
while (a < 5) {
a++;
if (a == 3) {
continue; // 当a的值自增到3时跳出本次循环
}
System.out.println("执行了while循环" + a + "次");
}
int b = 0;
do {
b++;
if (b == 3) {
continue; // 当b的值自增到3时跳出本次循环
}
System.out.println("执行了do-while循环" + b + "次");
} while (b < 5);
for (int c = 1; c <= 5; c++) {
if (c == 3) {
continue; // 当c的值自增到3时跳出本次循环
}
System.out.println("执行了for循环" + c + "次");
}
}
}
运行测试:
执行了while循环1次
执行了while循环2次
执行了while循环4次
执行了while循环5次
执行了do-while循环1次
执行了do-while循环2次
执行了do-while循环4次
执行了do-while循环5次
执行了for循环1次
执行了for循环2次
执行了for循环4次
执行了for循环5次
可以看到当以上循环都执行到第3次的时候,遇到continue
语句直接跳出本次循环了,所以continue
语句后面的输出语句不会执行。