顺序结构
顺序结构是 Java 程序默认的执行流程:按照代码的先后顺序,从上到下依次执行。
例如,下面这段代码会先打印 1,再打印 2,最后打印 3。
public class Test1 {
public static void main(String[] args) {
System.out.println(1);
System.out.println(2);
System.out.println(3);
}
}分支结构
顺序结构会一路往下执行,而分支结构可以根据条件决定执行哪一段代码。Java 中常用的分支语句有 if 和 switch。
if 语句
if 适合根据条件进行判断,常见的写法有三种:单分支、双分支和多分支。
第一种:单分支 if
基本格式:
if (条件表达式) {
语句体;
}先判断括号中的条件表达式。如果结果是 true,就执行大括号里的语句;如果是 false,就跳过这部分代码,继续向下执行。
例如,想判断输入的整数是不是正三位数,只需要判断它是否位于 100~999 之间。写成 Java 条件就是 num >= 100 && num < 1000。
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
if(num<1000&&num>=100)
{
System.out.println(num+"是三位数");
}
}
}这里有两个小细节:
- 大括号
{可以另起一行,不过通常建议写在if条件这一行的末尾,这样更紧凑。 - 如果
if中只有一条语句,大括号可以省略。下面这段代码也可以正常运行:
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
if (num < 1000 && num >= 100)
System.out.println(num + "是三位数");
}
}不过,如果后面需要再增加语句,忘记补上大括号就容易出问题,所以实际编写时保留大括号通常更稳妥。
判断布尔变量时,还要特别注意 = 和 == 的区别。 比如先定义 boolean flag = false;,本来只是想判断它的值,却手误写成 if (flag = true),这里的 = 是赋值,flag 会被改成 true,整个条件自然也就成立了。
对于布尔变量,直接写 if (flag) 就能判断它是否为 true,不需要额外写 == true。这样更简洁,也能避免把赋值写成比较的失误。
第二种:双分支 if...else
基本格式:
if (条件表达式) {
语句体1;
} else {
语句体2;
}程序先判断条件表达式:如果为 true,就执行语句体 1;否则执行语句体 2。两条分支只会选择其中一条,执行完再继续后面的代码。
这种结构就是二选一。例如,判断一个整数是奇数还是偶数:一个整数不是偶数,就是奇数。
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
if(num%2==0)
{
System.out.println(num+"是偶数");
} else {
System.out.println(num+"是奇数");
}
}
}这里用 num % 2 == 0 判断能否被 2 整除。成立就打印“偶数”,否则打印“奇数”。
第三种:多分支 if...else if...else
当需要判断的不止两种情况时,可以接着写 else if:
if (条件表达式1) {
语句体1;
} else if (条件表达式2) {
语句体2;
} else if (条件表达式3) {
语句体3;
} else {
其他情况对应的语句体;
}执行过程可以理解为:
- 先判断条件表达式 1,为
true就执行语句体 1,后面的分支不再判断。 - 如果条件 1 不满足,就继续判断条件 2;满足就执行语句体 2。
- 依次往下判断,直到找到第一个满足的条件。
- 如果所有条件都不满足,就执行最后的
else(如果写了的话)。
例如,我们根据分数划分等级:90 分及以上为 A,80~89 分为 B,70~79 分为 C,60~69 分为 D,60 分以下为 E(这里假设输入的是 0~100 的有效分数)。
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int score = sc.nextInt();
if (score >= 90) {
System.out.println("A");
} else if (score >= 80) {
System.out.println("B");
} else if (score >= 70) {
System.out.println("C");
} else if (score >= 60) {
System.out.println("D");
} else {
System.out.println("E");
}
}
}注意一个细节:程序已经判断过 score >= 90,当它继续判断 score >= 80 时,就不需要再写 score < 90 了。因为能走到第二个分支,就说明第一个条件没有成立。
简单来说,if...else if...else 会从上到下依次判断,一旦某个条件成立,就只执行对应分支;如果都不满足,就走最后的 else。
switch 语句
switch 也可以进行多分支选择。与 if...else if 不同,传统的 switch 更适合把一个表达式的结果与几个确定的值进行匹配,而不是直接判断一段数值范围。
基本格式与执行流程
switch (表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
default:
其他情况的语句体;
break;
}这里的 case、break、default 分别起到不同作用:
switch (表达式):先计算表达式的值,再寻找匹配的case。case:标记一个可匹配的值。传统switch中常见的是字面量,也可以使用符合要求的编译期常量表达式,但不能直接用普通变量或写成score >= 90这样的条件。break:执行到这里就退出当前switch,避免接着执行后面的分支。default:没有任何case匹配时,从这里开始执行。它的作用类似if...else if...else结构中最后的else,用于处理前面都没有匹配到的情况。
传统 switch 常见的匹配类型有 byte、short、char、int、枚举和 String(以及部分对应包装类型)。枚举支持从 Java 5 开始,String 支持从 Java 7 开始。较新的 Java 版本还有更多 switch 能力,这里先掌握最常用的形式。
同一个 switch 中不能出现重复的常量匹配值。
用 switch 判断分数等级
上面使用 if...else if 判断成绩,是直接比较分数区间。换成传统 switch 时,可以利用整数除法:int 类型相除会舍去小数部分,例如 95 / 10 得到 9,83 / 10 得到 8。
这里仍假设输入的是 0~100 分的有效成绩。这样就能把 90~99 分、80~89 分等区间转换成对应的整数;100 分除以 10 得到 10,因此需要用 case 10 单独匹配。
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int score = sc.nextInt();
switch(score/10)
{
case 10:
System.out.println("A");
break;
case 9:
System.out.println("A");
break;
case 8:
System.out.println("B");
break;
case 7:
System.out.println("C");
break;
case 6:
System.out.println("D");
break;
default:
System.out.println("E");
break;
}
}
}当 score / 10 得到 10 或 9 时,都会输出 A;得到 8、7、6 时,分别输出对应等级;其余情况走 default。在 0~100 分的前提下,五个等级就都覆盖到了。
还有一点值得区分:if...else if 是依次判断条件,而 switch 是根据表达式的值找到匹配入口。它们都能完成多分支选择,但具体执行方式并不完全一样。
default 的位置与省略
default 并不一定要放在最后,也可以写在 case 的前面或中间。无论它写在哪里,程序都会先寻找能匹配的 case;只有都匹配不到,才从 default 开始执行。
看下面这段代码,default 被放在最前面:
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int score = sc.nextInt();
switch (score / 10) {
default:
System.out.println("E");
break;
case 10:
System.out.println("A");
break;
case 9:
System.out.println("A");
break;
case 8:
System.out.println("B");
break;
case 7:
System.out.println("C");
break;
case 6:
System.out.println("D");
break;
}
}
}虽然 default 写在最前面,但它并不会优先执行。例如,输入 95 时会匹配 case 9,输出 A;输入 50 时没有符合的 case,才会执行 default,输出 E。
可见,default 放在哪里,不影响程序选择哪个分支。这里每个分支都用 break 结束,确保只输出对应的等级。
另外,传统 switch 的 default 也可以省略。如果没有任何 case 匹配、又没有 default,那么这个 switch 就不会执行任何分支。如果需要处理所有未匹配的情况,可以保留 default 作为兜底分支。
case 穿透
传统 switch 中,一旦匹配到某个 case,如果没有遇到 break,就会继续执行后面分支的语句体,不再重新判断后面那些 case 是否匹配。这种现象叫作 case 穿透。
执行过程可以这样理解:先根据表达式的值找到执行入口,然后一路向下执行,直到遇到 break,或者执行到 switch 的右大括号。
例如,把前面成绩判断中的 break 全部去掉。这里让 case 10 和 case 9 共用打印 A 的语句,以便 100 分与 90~99 分从同一处开始执行:
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int score = sc.nextInt();
switch (score / 10) {
case 10:
case 9:
System.out.println("A");
case 8:
System.out.println("B");
case 7:
System.out.println("C");
case 6:
System.out.println("D");
default:
System.out.println("E");
}
}
}输入 90 时,会从 case 9 开始,依次输出 A、B、C、D、E:
90
A
B
C
D
E输入 73 时,会从 case 7 开始,依次输出 C、D、E:
73
C
D
E所以,传统 switch 中如果只想执行一个分支,通常需要用 break 防止穿透。当然,在确实需要多个分支共享执行逻辑的场景中,也可以有意利用这种特性。
箭头语法:case ... ->
从 Java 12 开始,switch 的新写法进入预览阶段,并在 Java 14 正式成为标准特性。其中一个明显变化,就是可以把传统的 case 值: 改成 case 值 ->。
这种写法不用在每个分支后手动添加 break,而且不会发生前面那种 case 穿透。先看带大括号的形式:
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int score = sc.nextInt();
switch (score / 10) {
case 10 -> {
System.out.println("A");
}
case 9 -> {
System.out.println("A");
}
case 8 -> {
System.out.println("B");
}
case 7 -> {
System.out.println("C");
}
case 6 -> {
System.out.println("D");
}
default -> {
System.out.println("E");
}
}
}
}如果箭头后面只有一条语句,还可以直接省略大括号:
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int score = sc.nextInt();
switch (score / 10) {
case 10 ->
System.out.println("A");
case 9 ->
System.out.println("A");
case 8 ->
System.out.println("B");
case 7 ->
System.out.println("C");
case 6 ->
System.out.println("D");
default ->
System.out.println("E");
}
}
}这两种箭头写法都不会向后穿透。case 10 对应 100 分,case 9 对应 90~99 分,二者都输出 A。
这里展示的是 switch 语句的新写法;switch 还可以作为表达式返回结果,不过先掌握分支选择就够用了。
循环结构
如果一段代码需要执行多次,逐行重复写就比较麻烦。这时可以使用循环结构,让程序在满足条件时反复执行同一段代码。
for 循环
for 常见的写法是:
for (初始化语句; 条件判断语句; 条件控制语句) {
循环体语句;
}可以按下面的顺序理解:
- 初始化:先执行初始化语句,这一步只会执行一次。
- 判断条件:如果条件为
true,就执行循环体;如果为false,循环直接结束。 - 更新变量:执行完循环体后,执行条件控制语句,再回到第 2 步重新判断。
例如,想打印五遍 helloworld:
public class Test1 {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
System.out.println("helloworld");
}
}
}一开始 i = 0,满足 i < 5,于是打印一次,然后执行 i++。接着重新判断,再打印、再加一……
当 i 分别为 0、1、2、3、4 时,循环体都会执行;等 i 增加到 5,判断条件不再成立,循环结束。所以一共执行了 5 次。
在这种写法中,初始化部分只执行一次;之后每次进入循环体前,都要重新判断条件。
while 循环
while 的基本写法是:
初始化语句;
while (条件判断语句) {
循环体语句;
条件控制语句;
}这里把初始化和变量更新单独写了出来,方便与上面的 for 对照。实际上,while 的核心语法只有 while (条件) { ... },是否需要初始化或更新变量,要看具体问题。
把刚才打印五遍 helloworld 的例子换成 while:
public class Test1 {
public static void main(String[] args) {
int i = 0;
while (i < 5) {
System.out.println("helloworld");
i++;
}
}
}程序先判断 i < 5。只要成立,就打印一次并让 i++;当 i 增加到 5,循环结束。和上面的 for 一样,这段代码也会打印五遍。
do...while 循环
do...while 和 for、while 的一个明显区别是:先执行循环体,再判断条件。因此,即使条件一开始就不成立,循环体也会至少执行一次。
基本格式:
初始化语句;
do {
循环体语句;
条件控制语句;
} while (条件判断语句);这里的初始化和条件控制语句是为了方便理解循环过程,实际写法可以根据需要调整。注意,do...while 末尾的 while (条件) 后面要有一个分号 ;。
例如:
public class Test1 {
public static void main(String[] args) {
int i = 10;
do{
System.out.println("helloworld");
i++;
} while (i < 10);
}
}这段代码中,i 一开始就是 10。程序不会先判断 i < 10,而是直接执行 do 中的代码,打印一次 helloworld,然后让 i 增加到 11。接着才判断 i < 10,由于条件不成立,循环结束。
如果换成 for 或 while,在进入循环体前就会判断条件,因此这里一次 helloworld 都不会打印。
do...while 在平时使用得相对少一些,现阶段先记住它至少执行一次循环体的特点即可。
for、while 与 do...while 的区别
for 和 while 都是先判断条件,再执行循环体;do...while 则是先执行一次,再判断是否继续循环。三者都能重复执行代码,只是判断条件的时机不同。
一个容易注意到的区别是循环变量的作用范围:
- 在上面的
for (int i = 0; ...)中,i定义在for的初始化部分,离开这个for后就不能继续使用。 - 在上面的
while示例中,i定义在循环外,所以循环结束后仍然可以使用。
但这并不是 for 和 while 天生的区别,而是变量声明的位置不同。如果把 for 的控制变量也声明在循环外,循环结束后一样可以访问。
实际选择时,可以简单记成:已知循环次数或明确的遍历范围,常用 for;主要依靠某个结束条件、循环次数不确定时,常用 while;需要至少执行一次循环体时,可以考虑 do...while。 这只是常见习惯,并不是硬性限制。
循环控制语句
有时我们不想等循环自然结束,而是想跳过当前这一轮,或在满足条件时提前停止。这就需要 continue 和 break。
continue:跳过本轮循环
continue 用于跳过当前这一次循环中剩余的语句,继续下一次循环。
例如,遍历 1~10,只打印偶数。如果当前数字是奇数,就执行 continue,跳过后面的打印语句:
public class Test1 {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i % 2 != 0)
continue;
System.out.println(i);
}
}
}在这个 for 循环中,遇到奇数后执行 continue,会转去执行本轮的 i++,然后重新判断 i <= 10。因此,奇数不会被打印,最后只输出 2、4、6、8、10。
break:提前结束循环
与 continue 只跳过本轮不同,break 会直接结束当前所在的循环,不再进入下一轮。(如果有多层嵌套循环,普通 break 默认只结束它所在的最内层循环。)
例如,我们想从 1 开始,按从小到大的顺序找到 5 个既能被 2 整除、又能被 3 整除的正整数。可以定义一个计数器 count,每找到一个满足条件的数字,就让 count 加 1。当找到第 5 个时,用 break 立即停止循环:
public class Test1 {
public static void main(String[] args) {
int count=0;
for(int i=1;i<1000;i++)
{
if(i%2==0&&i%3==0)
count++;
if (count >= 5)
{
System.out.println("已经找到5个可以被2整除又可以被3整除的数字了");
break;
}
}
}
}这段代码会从 1 开始逐个检查:如果一个数同时满足 i % 2 == 0 和 i % 3 == 0,就将 count 加 1。符合条件的前五个正整数依次是 6、12、18、24、30。
当 count 增加到 5 时,程序打印提示信息并执行 break,直接退出 for 循环,不必再检查后面的数字。这里的 count 用来记录找到的数量,代码只打印完成提示,并不会逐个打印这五个数字。
聊两句
评论审核后显示有疑问、补充,或者想交流一下,都可以写在这里。
评论区将在滚动到这里时加载。