JavaSE3️⃣程序基础 - 流程控制&数组操作
1、流程控制
在 Java 中,分号
;
作为语句结束。使用流程控制语句,可实现条件判断、循环、程序跳转等功能。
1.1、输入输出
Java 内置
System
类中,提供了输入输出相关功能。
- System.out:标准输出流。
- System.err:标准错误输出流。
- System.in:标准输入流。
1.1.1、out
标准输出流
-
println():打印并换行(print line)。
System.out.println("A"); System.out.println("B"); /* 输出内容 A B */
-
print():打印。
System.out.print("A"); System.out.print("B"); /* 输出内容 AB */
-
printf():格式化打印(format)。
-
占位符(
%
):按指定格式打印内容。占位符 说明 %d 输出十进制整数 %x 输出十六进制整数 %f 输出浮点数 %e 输出科学计数法表示的浮点数 %s 字符串 -
示例:
// 整数:23 System.out.printf("整数:%d", 23); // 十六进制:1e System.out.printf("十六进制:%x", 30); // 浮点数:3.14 System.out.printf("浮点数:%.2f", 3.1415);
-
1.1.2、err
标准错误输出流:用于打印错误消息、用户应立即注意的信息。
用法与 out 相同,区别是以红色字体输出。
// 整数:23
System.err.printf("整数:%d", 23);
// 十六进制:1e
System.err.printf("十六进制:%x", 30);
// 浮点数:3.14
System.err.printf("浮点数:%.2f", 3.1415);
1.1.3、in
标准输入流:需要结合 Scanner(简单的文本扫描程序)使用。
- 导包:
java.util.Scanner
- 创建对象:传入标准输入流作为参数。
- 读取用户输入:
- next()
- nextLine()
- nextInt(), nextDouble() ...
- 运行程序
示例:计算 BMI(公式 = 体重 / 身高2)
import java.util.Scanner;
public class CalculateBMI {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("输入身高(m):");
double height = scanner.nextDouble();
System.out.print("输入体重(kg):");
double weight = scanner.nextDouble();
System.out.printf("BMI:%.2f", weight / (height * height));
}
}
1.2、条件判断
1.2.1、if
① 语法
-
if:若布尔表达式成立(true),执行代码块。
if (布尔表达式) { // 代码 }
-
if-else:若布尔表达式不成立(false),执行 else 代码块。
if (布尔表达式1) { // 代码 } else { // 代码 }
-
多重 if:依次判断布尔表达式,直到成立。
if (布尔表达式1) { // 代码1 } else if (布尔表达式2) { // 代码2 } else if (布尔表达式n) { // 代码n } else { // 代码3 }
② 示例
-
判断成绩是否合格:
Scanner scanner = new Scanner(System.in); int score = scanner.nextInt(); if (score >= 60) { System.out.println("合格"); } else { System.out.println("不合格"); }
-
判断成绩等级:
Scanner scanner = new Scanner(System.in); int score = scanner.nextInt(); if (score < 60) { System.out.println("D"); } else if (score < 80) { System.out.println("C"); } else if (score < 90) { System.out.println("B"); } else { System.out.println("A"); }
③ 使用说明
-
使用:
- 若代码块只包含一条语句,可省略
{}
(不推荐使用)。 - if 是必须的,else 是可选的。
- 若代码块只包含一条语句,可省略
-
条件范围:多重 if 语句中,小范围条件在前,大范围条件在后。
-
临界值:根据业务需求,需要判断布尔表达式中的不等号是否取临界值
=
。 -
不同数据类型的判断相等:
-
基本类型:
==
(浮点数除外,需要判断差值是否小于很小的值) -
引用类型:
equals()
,注意 NPE 问题。// 基本类型 int score = 60; if (score == 60) { // ... } // 基本类型——浮点数 double base = 0.00001; double x; if (Math.abs(x - 0.1) < base) { System.out.println("x 是 0.1"); } // 引用类型:短路运算符&&避免NPE String str = "Hello"; if (str != null && str.equals("Hello")) { // ... }
-
1.2.2、switch
① 语法
-
根据表达式计算结果,匹配相应的 case 并跳转执行。
-
执行 case 中的代码,直到关键字
break
结束。 -
若没有匹配到任何 case 结果,执行
default
代码块(若有)。switch (表达式) { case 情况1: // 代码1 break; case 情况2: // 代码2 break; default: // 默认代码 break; }
② 示例
System.out.println("请选择游戏选项:")
int option = scanner.nextInt();
switch (option) {
case 1:
System.out.println("1-单人游戏");
break;
case 2:
System.out.println("2-双人游戏");
break;
case 3:
System.out.println("3-退出游戏");
break;
default:
System.out.println("输入有误");
break;
}
③ 使用说明
- 使用:在选项较多的情况下,使用
switch-case
比多重 if 结构更清晰。 - case 的特点:
- 穿透性:若没有使用
break
结束case
语句块,默认会执行之后所有 case 代码块。 - 顺序:在正确使用
break
的基础上,不需要考虑多个 case 的顺序。
- 穿透性:若没有使用
- switch 版本特性:
- 5-:支持 byte, short, int, char 及其包装类型。
- 5:支持 switch 枚举。
- 7:支持 switch 字符串。
- 12:引入新语法。
- switch 可返回值,case 无需 break 语句。
- 引入 yield 关键字用于返回值。
1.3、循环
指定循环条件,满足时执行循环,不满足时跳出。
1.3.1、while
先判断条件,再执行循环体。
-
语法:每次执行循环前,判断条件是否成立。
-
true:执行一遍循环体。
-
false:跳到 while 循环末尾,执行后续代码。
while (布尔表达式) { // 循环体 } // 后续代码
-
-
至少执行次数:1 次布尔表达式计算,0 次循环体。
-
注意:
- 计数器:先执行代码逻辑,再更新计数器。
- 死循环:若 while 条件有误,可能导致程序死循环,CPU 占满。
示例:计算从 low 到 high 的所有整数之和。
int low = 100, high = 300;
int sum = 0;
int i = low; // 计数器
// while计算
while (i <= high) {
sum += i;
i++;
}
System.out.println(sum);
// 验证答案
int result = (low + high) * (high - low + 1) / 2;
System.out.println(result);
1.3.2、do-while
先执行循环体,再判断条件。
-
语法:每次循环中先执行循环体,再判断条件是否成立。
-
true:执行一遍循环体。
-
false:跳到 do-while 循环末尾,执行后续代码。
do { // 循环体 } while (布尔表达式);
-
-
至少执行次数:1 次循环体,1 次布尔表达式计算。
-
注意:计数器的正确使用、死循环的避免。
示例:计算从 low 到 high 的所有整数之和。
int low = 100, high = 300;
int sum = 0;
int i = low;
// while计算
do {
sum += i;
i++;
} while (i <= high);
System.out.println(sum);
// 验证答案
int result = (low + high) * (high - low + 1) / 2;
System.out.println(result);
1.3.3、for
使用计数器
-
语法:初始化计数器,每次循环前判断条件是否成立。
-
true:执行循环体,更新计数器。
-
false:跳到 for 循环末尾,执行后续代码。
// 简单循环 for (初始化语句; 结束条件; 更新语句) { // 循环体 } // 嵌套循环 for (初始化语句; 结束条件; 更新语句) { for (初始化语句; 结束条件; 更新语句) { // 循环体 } }
-
-
至少执行次数:
- 1 次初始化语句(若有)。
- 1 次结束条件判断(若有)。
- 0 次循环体,0 次更新语句。
-
注意:
- 应避免过多层级的嵌套 for 循环。
- 临界值:根据业务需求,需要判断初始化条件和结束条件是否取等号
=
。 - 灵活性:for 可以缺少初始化语句、结束条件、更新语句中的任意一个或多个。
- 计数器更新:若定义了更新语句,则尽量避免在循环体中手动更新计数器。
- 功能强化:Java 5 引入增强 for 循环(
foreach
),简化可迭代数据类型(如数组、集合)的遍历操作。
示例
-
计算从 low 到 high 的所有整数之和。
int low = 100, high = 300; int sum = 0; // while计算 for (int i = low; i <= high; i++) { sum += i; } System.out.println(sum); // 验证答案 int result = (low + high) * (high - low + 1) / 2; System.out.println(result);
-
输出数组中的所有元素。
String[] array = {"A", "B", "C"}; // for for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } // foreach for (String str : array) { System.out.println(str); }
1.4、跳转
-
使用:在循环体中使用,跳出循环。
- 通常配合
if
,在满足条件时跳出循环。 - 嵌套循环中,只跳出当前一层。
- 通常配合
-
关键字:
- break:跳出当前循环。
- continue:提前结束本轮循环,执行下一轮。
-
示例:
for (int i = 1; ; i++) { // 跳过偶数 if (i & 2 == 0) { continue; } // 结束循环 if (i == 50) { break; } } // 嵌套循环 for (int i = 1; i < 10; i++) { for (int j = 1; j < 10; j++) { if (...) { break; } } // break跳到这里 }
2、数组操作
2.1、遍历
遍历(traverse):通过索引下标,访问数组的每一个元素。
2.1.1、一维数组
按实际需求,选择适合的遍历形式。
-
for:通过索引访问元素。
int[] nums = {1, 2, 3, 4, 5}; for (int i = 0; i < nums.length; i++) { System.out.print(nums[i] + " "); }
-
foreach:按顺序访问元素。
for (int num : nums) { System.out.print(num + " "); }
-
Arrays.toString():将数组内容转换成字符串形式。
System.out.println(Arrays.toString(nums));
2.1.2、二维数组
按实际需求,选择适合的遍历形式。
-
双层 for:通过索引访问元素。
int[][] nums = { {1, 2, 3}, {4, 5, 6, 7}, {8, 9} }; for (int i = 0; i < nums.length; i++) { for (int j = 0; j < nums[i].length; j++) { System.out.print(nums[i][j] + " "); } System.out.println(); }
-
双层 foreach:按顺序访问数组/元素。
for (int[] num : nums) { for (int n : num) { System.out.print(n + " "); } System.out.println(); }
-
结合 for/foreach:
for (int i = 0; i < nums.length; i++) { for (int num : nums[i]) { System.out.print(num + " "); } System.out.println(); } for (int[] num : nums) { for (int j = 0; j < num.length; j++) { System.out.print(num[j] + " "); } System.out.println(); }
-
Arrays.deepToString()
:将数组内容转换成字符串形式。System.out.println(Arrays.deepToString(nums));
2.2、排序
排序(sort):将数组元素按一定规则进行排列,会修改数组内容。
常用排序方式:冒泡、插入、归并、快排、堆....
2.2.1、冒泡排序
- 特点:每轮循环中,依次比较相邻的两个元素,若顺序错误则交换。
- 命名由来:每个元素都像气泡一样,在每次循环后最大(最小)的元素浮到数组的末尾。
示例:升序排序。
-
双层 for:外层代表循环次数,内层用于依次比较相邻元素。
-
临界条件:
- 外层:前 n - 1 次循环即可完成排序,第 n 次循环无意义(只有一个元素,无需比较)
- 内层:每经过一轮循环,新一轮中需要比较的元素个数 - 1。
-
交换:定义临时变量 tmp 进行交换。
int[] nums = {10, 5, 37, 20, 3, 1, 58}; // 冒泡排序 for (int i = 0; i < nums.length - 1; i++) { for (int j = 0; j < nums.length - 1 - i; j++) { if (nums[j] > nums[j + 1]) { int tmp = nums[j]; nums[j] = nums[j + 1]; nums[j + 1] = tmp; } } }
2.2.2、Arrays.sort()
Arrays 工具类提供
sort()
方法,数组长度 n 决定排序方式。插入/快排/归并
- [1, 47):插入
- [47, 286):快排
- [286, +∞):
- 无结构:快排
- 有结构:归并
2.3、命令行参数
main
方法:Java 程序的入口
- 方法参数列表:一个 String 数组,用于接收命令行参数。
- 使用方式:
- 通过命令行方式运行 Java 程序时,JVM 会接收用户输入的参数,传给 main 方法。
- 由程序员自行编写相应的解析规则。
示例:传入版本
-
编写程序:
public class MyMain { public static void main(String[] args) { for (String arg : args) { if ("-version".equals(arg)) { // do something ... break; } } } }
-
编译并运行:打开 MyMain 所在的命令行窗口。
# 编译 javac MyMain.java # 运行:传入参数 java MyMain -version
-
args:JVM 接收 -version,传给 main 方法
// args内容:["-version"]
-
程序遍历 args 数组,找到 -version,执行代码
// do something ... break;