Java学习第3节分支语句,数组与方法
Java 学习第 3 节:流程控制、数组与方法
文章目录
前言
在前面的学习中,我们已经接触了 Java 的变量、数据类型、运算符等基础知识。
本节将继续学习 Java 中非常重要的三部分内容:
- 流程控制语句:
if、switch、for、while - 数组:一维数组、二维数组以及数组的常见操作
- 方法:方法的定义、参数传递以及方法重载
这些知识是后续学习面向对象、集合、算法以及实际项目开发的重要基础。
一、流程控制语句
程序默认按照代码从上到下依次执行。
但在实际开发中,我们经常需要:
- 根据不同条件执行不同代码
- 重复执行某段代码
因此,Java 提供了分支语句和循环语句。
1. switch 分支语句
switch 语句适合处理一个变量存在多个固定取值的情况。
基本格式如下:
switch (表达式) {
case 值1:
执行语句1;
break;
case 值2:
执行语句2;
break;
default:
默认执行语句;
break;
}
执行流程
程序会将 switch 中表达式的结果依次与每个 case 后面的值进行匹配:
- 如果匹配成功,则从对应的
case开始执行。 - 遇到
break时,立即结束整个switch。 - 如果所有
case都没有匹配成功,则执行default。 default可以省略。
例如:
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int data = sc.nextInt();
switch (data) {
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
case 5:
System.out.println("星期五");
break;
case 6:
System.out.println("星期六");
break;
case 7:
System.out.println("星期日");
break;
default:
System.out.println("输入错误");
break;
}
sc.close();
}
}
switch 穿透现象
需要特别注意:
case可以理解为程序执行的入口,而break可以理解为当前分支的出口。
如果匹配到某个 case 后没有遇到 break,程序会继续向下执行后面的代码,这种现象称为:
case 穿透
例如:
int data = 1;
switch (data) {
case 1:
System.out.println("A");
case 2:
System.out.println("B");
case 3:
System.out.println("C");
break;
}
运行结果:
A
B
C
原因是:
data匹配case 1- 执行
"A" - 没有遇到
break - 继续执行
case 2 - 继续执行
case 3 - 最后遇到
break
因此,在普通分支判断中,通常需要注意是否应该添加 break。
2. if 分支语句
if 的意思是“如果”。
它用于根据一个布尔条件决定是否执行某段代码。
Java 中常见的 if 语句有三种格式。
2.1 单分支 if
格式:
if (布尔表达式) {
执行语句;
}
执行流程:
- 判断
if后面的布尔表达式。 - 如果结果为
true,执行大括号中的代码。 - 如果结果为
false,跳过if代码块。
例如:
int age = 20;
if (age >= 18) {
System.out.println("已经成年");
}
2.2 双分支 if…else
格式:
if (布尔表达式) {
执行语句1;
} else {
执行语句2;
}
执行流程:
- 判断
if后面的条件。 - 如果结果为
true,执行语句 1。 - 如果结果为
false,执行语句 2。
例如:
int age = 16;
if (age >= 18) {
System.out.println("已经成年");
} else {
System.out.println("尚未成年");
}
2.3 多分支 if…else if…else
格式:
if (条件1) {
执行语句1;
} else if (条件2) {
执行语句2;
} else if (条件3) {
执行语句3;
} else {
执行语句n;
}
执行流程:
从上到下依次判断:
- 如果条件 1 为
true,执行语句 1,然后结束整个分支结构。 - 否则继续判断条件 2。
- 哪个条件最先为
true,就执行对应代码。 - 如果前面的所有条件都为
false,则执行最后的else。
例如:
int score = 85;
if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
运行结果:
良好
二、循环语句
循环语句用于重复执行某段代码。
Java 中常见的循环包括:
forwhiledo...while
本节重点介绍 for 和 while。
1. for 循环
基本格式:
for (初始化语句; 条件判断; 步进表达式) {
循环体;
}
例如:
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
运行结果:
0
1
2
3
4
5
6
7
8
9
执行流程
初始化
↓
判断条件
↓ true
执行循环体
↓
执行步进表达式
↓
重新判断条件
具体步骤:
- 执行初始化语句,例如
int i = 0 - 判断循环条件,例如
i < 10 - 如果条件为
true,执行循环体 - 执行步进表达式,例如
i++ - 再次判断条件
- 重复以上过程
- 当条件为
false时结束循环
需要注意:
初始化语句通常只执行一次。
2. while 循环
基本格式:
初始化语句;
while (条件判断) {
循环体;
步进表达式;
}
例如:
public class Demo {
public static void main(String[] args) {
int i = 0;
while (i < 3) {
System.out.println(i);
i++;
}
}
}
运行结果:
0
1
2
执行流程
- 初始化变量
- 判断
while条件 - 如果条件为
true,执行循环体 - 修改循环变量
- 再次判断
- 当条件为
false时结束循环
从逻辑上看,下面两个循环基本等价:
for (int i = 0; i < 3; i++) {
System.out.println(i);
}
与:
int i = 0;
while (i < 3) {
System.out.println(i);
i++;
}
for 和 while 的简单区别
当循环次数比较明确时,通常使用:
for
当循环次数不明确,只知道循环结束条件时,通常使用:
while
例如:
while (用户没有退出程序) {
继续运行;
}
三、Scanner 键盘输入
在正式介绍数组之前,先简单了解 Java 中的键盘输入。
Java 可以使用 Scanner 类接收用户从键盘输入的数据。
1. Scanner 的基本使用
第一步:导包
import java.util.Scanner;
第二步:创建 Scanner 对象
Scanner sc = new Scanner(System.in);
第三步:调用方法读取输入
读取整数:
int data = sc.nextInt();
读取字符串:
String str = sc.next();
完整示例:
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 录入一个整数
int data1 = sc.nextInt();
System.out.println(data1);
// 录入一个字符串
String data2 = sc.next();
System.out.println(data2);
sc.close();
}
}
2. 常见输入方法
| 方法 | 作用 |
|---|---|
nextInt() |
读取 int 类型整数 |
nextDouble() |
读取 double 类型小数 |
next() |
读取一个字符串,以空白字符为分隔 |
nextLine() |
读取一整行字符串 |
例如:
String name = sc.next();
如果输入:
Zhang San
next() 通常只读取:
Zhang
而:
String name = sc.nextLine();
可以读取整行内容:
Zhang San
四、数组
1. 数组简介
数组可以理解为:
一个用于存储多个相同类型数据的容器。
例如,现在需要存储 5 个学生的成绩。
如果不用数组:
int score1 = 90;
int score2 = 80;
int score3 = 70;
int score4 = 95;
int score5 = 85;
使用数组:
int[] scores = {90, 80, 70, 95, 85};
显然更加简洁。
2. 数组的特点
2.1 数组属于引用类型
例如:
int[] arr = new int[3];
变量 arr 保存的不是数组中的某个具体整数,而是对数组对象的引用。
2.2 一个数组可以存储多个数据
例如:
int[] arr = {1, 2, 3, 4, 5};
2.3 数组长度固定
数组一旦创建,其长度不能改变。
例如:
int[] arr = new int[3];
这个数组的长度永远是:
3
注意:
数组中的元素值可以修改,但是数组本身的长度不能修改。
2.4 数组中的元素类型统一
例如:
int[] arr = {1, 2, 3};
这个数组只能保存 int 类型的数据。
下面的写法错误:
int[] arr = {1, "hello", 3};
因为 "hello" 是 String 类型。
五、数组的定义
1. 动态初始化
格式:
数据类型[] 数组名 = new 数据类型[数组长度];
例如:
int[] arr1 = new int[3];
String[] arr2 = new String[3];
表示:
int[] arr1 = new int[3];
创建一个能够保存 3 个 int 元素的数组。
另一种语法也合法:
int arr1[] = new int[3];
不过在 Java 中更加推荐:
int[] arr1 = new int[3];
因为这种写法更清晰地表示:
arr1是一个int[]类型的变量。
2. 完整静态初始化
格式:
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元素3};
例如:
int[] arr = new int[]{1, 2, 3, 4, 5};
3. 简化静态初始化
格式:
数据类型[] 数组名 = {元素1, 元素2, 元素3};
例如:
int[] arr1 = {1, 2, 3, 4, 5};
String[] arr2 = {"a", "b", "c"};
这是静态初始化中非常常见的写法。
完整示例:
public class Demo {
public static void main(String[] args) {
// 动态初始化
int[] arr1 = new int[3];
String[] arr2 = new String[3];
// 静态初始化
int[] arr3 = {1, 2, 3, 4, 5};
String[] arr4 = {"a", "b", "c"};
}
}
六、数组的基本操作
1. 获取数组长度
通过:
数组名.length
获取数组长度。
例如:
int[] arr = {1, 2, 3};
System.out.println(arr.length);
运行结果:
3
注意:
数组的 length 是一个属性,因此:
arr.length
后面没有括号。
2. 数组索引
索引表示元素在数组中的位置。
需要牢记:
Java 数组的索引从 0 开始。
例如:
String[] arr = {"a", "b", "c"};
对应关系:
| 索引 | 元素 |
|---|---|
0 |
"a" |
1 |
"b" |
2 |
"c" |
因此:
arr[0]
表示:
"a"
而:
arr[2]
表示:
"c"
3. 存储和修改元素
可以根据索引给数组元素赋值:
int[] arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
也可以修改已经存在的元素:
arr[1] = 100;
此时数组变成:
[1, 100, 3]
4. 获取数组元素
通过:
数组名[索引]
获取元素。
例如:
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
5. 遍历数组
遍历数组是指:
将数组中的所有元素依次访问一次。
可以使用 for 循环:
int[] arr = {10, 20, 30, 40};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
执行过程:
i = 0 → arr[0]
i = 1 → arr[1]
i = 2 → arr[2]
i = 3 → arr[3]
当:
i = 4
条件:
i < arr.length
即:
4 < 4
结果为 false,循环结束。
6. 数组索引越界
例如:
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
这是错误的。
因为数组长度为 3,合法索引只有:
0
1
2
访问 arr[3] 会发生数组索引越界异常。
因此,一个长度为 n 的数组,其合法索引范围是:
0 ~ n - 1
七、二维数组
1. 二维数组简介
如果一维数组可以理解为“一行数据”,那么二维数组可以理解为:
由多个一维数组组成的数组。
例如:
int[][] arr = {
{1, 2, 3},
{4, 5, 6}
};
可以理解为:
1 2 3
4 5 6
其中:
arr[0]
表示第一行:
1 2 3
而:
arr[1]
表示第二行:
4 5 6
2. 二维数组索引
例如:
arr[i][j]
其中:
i表示第一个维度的索引,可以理解为行索引j表示第二个维度的索引,可以理解为列索引
例如:
arr[1][2]
表示:
- 第
1 + 1 = 2行 - 第
2 + 1 = 3列
也就是:
第 2 行第 3 列
需要特别注意:
arr[3][5]
表示的是:
第 4 行第 6 列
但这并不意味着数组本身“有 3 行 5 列”。
3 和 5 在这里是索引值,不是数组长度。
3. 动态初始化
格式:
数据类型[][] 数组名 = new 数据类型[m][n];
例如:
int[][] arr = new int[3][4];
表示:
- 二维数组中有 3 个一维数组
- 每个一维数组长度为 4
通常可以直观理解为:
3 行 4 列
其中:
m
表示外层数组长度。
n
表示每个内层一维数组的长度。
4. 静态初始化
完整格式:
int[][] arr = new int[][]{
{1, 2},
{3, 4},
{5, 6}
};
5. 简化静态初始化
int[][] arr = {
{1, 2},
{3, 4},
{5, 6}
};
6. 获取二维数组元素
例如:
int[][] arr = {
{1, 2, 3},
{4, 5, 6}
};
访问:
System.out.println(arr[0][0]);
结果:
1
访问:
System.out.println(arr[1][2]);
结果:
6
7. 遍历二维数组
使用两层 for 循环:
int[][] arr = {
{1, 2, 3},
{4, 5, 6}
};
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
其中:
arr.length
表示外层数组长度,也就是这里的“行数”。
arr[i].length
表示第 i 个一维数组的长度。
这种写法比直接写固定列数更加安全。
八、方法
1. 方法简介
在 C 或 C++ 中,如果要实现某个独立功能,例如:
- 两数相加
- 排序
- 查找最大值
通常会定义一个函数。
Java 中也有类似概念,称为:
方法(Method)
方法可以理解为:
一段用于完成特定功能,并且可以被重复调用的代码。
例如:
public static void printHello() {
System.out.println("Hello");
}
调用:
printHello();
2. 方法的一般定义格式
修饰符 返回值类型 方法名(参数列表) {
方法体;
return 返回结果;
}
例如:
public static int add(int a, int b) {
int result = a + b;
return result;
}
调用:
int result = add(10, 20);
System.out.println(result);
运行结果:
30
九、方法的四种常见形式
根据:
- 是否有参数
- 是否有返回值
可以将方法分为四种常见形式。
1. 无参无返回值
public static void printHello() {
System.out.println("Hello");
}
特点:
- 没有参数
- 返回值类型为
void - 不返回结果
调用:
printHello();
2. 有参无返回值
public static void printHello(int a) {
if (a == 1) {
System.out.println("Hello");
} else {
System.out.println("Wrong");
}
}
调用:
printHello(1);
3. 无参有返回值
public static int getZero() {
return 0;
}
调用:
int result = getZero();
System.out.println(result);
4. 有参有返回值
public static String getMessage(int a) {
if (a == 1) {
return "Hello";
} else {
return "Wrong";
}
}
调用:
String result = getMessage(1);
System.out.println(result);
运行结果:
Hello
十、方法参数传递
1. 形参与实参
例如:
public static void main(String[] args) {
int x = 10;
method(x);
}
public static void method(int a) {
System.out.println(a);
}
调用方法时:
method(x);
这里的:
x
叫做:
实际参数,简称实参
而方法定义中的:
int a
叫做:
形式参数,简称形参
2. Java 参数传递的本质
需要特别注意:
Java 中的方法参数传递统一采用值传递。
这是一个非常重要的概念。
无论是:
- 基本数据类型
- 引用数据类型
本质上都是:
值传递
只是传递的“值的内容”不同。
3. 基本数据类型作为参数
对于基本数据类型,传递的是:
基本类型变量中保存的具体值的副本。
例如:
public class Demo {
public static void main(String[] args) {
int a = 1;
int b = 10;
method(a, b);
System.out.println(a); // 1
System.out.println(b); // 10
}
public static void method(int a, int b) {
a += 1;
b += 10;
System.out.println(a); // 2
System.out.println(b); // 20
}
}
运行过程可以简单理解为:
调用:
method(a, b);
相当于把:
1
10
复制给方法中的形参。
也就是:
public static void method(int a, int b)
内部可以理解为获得了新的局部变量:
a = 1
b = 10
因此:
a += 1;
b += 10;
只改变方法内部的形参。
不会改变 main 方法中的原变量。
最终:
main 中的 a = 1
main 中的 b = 10
4. 引用类型作为参数
对于数组、对象等引用类型,传递的仍然是:
值的副本。
只不过这个值是:
引用值的副本。
例如:
public class Demo {
public static void main(String[] args) {
int[] arr = {1, 2};
method(arr);
System.out.println(arr[0]); // 2
System.out.println(arr[1]); // 12
}
public static void method(int[] arr) {
arr[0] += 1;
arr[1] += 10;
System.out.println(arr[0]); // 2
System.out.println(arr[1]); // 12
}
}
为什么方法内部修改数组后,原数组也变化了?
因为:
main 方法中的 arr
与:
method 方法中的 arr
虽然是两个不同的变量,但它们保存的引用值指向同一个数组对象。
可以简单理解为:
main 中的 arr ──────┐
↓
[1, 2]
↑
method 中的 arr ────┘
所以:
arr[0] += 1;
修改的是同一个数组对象中的元素。
最终原数组也会发生变化。
5. 一个非常重要的区别
下面这种操作会影响原数组:
public static void method(int[] arr) {
arr[0] = 100;
}
因为修改的是:
同一个数组对象内部的元素
但是下面这种情况不同:
public static void method(int[] arr) {
arr = new int[]{100, 200};
}
这里只是让方法内部的形参 arr 指向一个新的数组。
不会改变外部变量原本保存的引用值。
例如:
public class Demo {
public static void main(String[] args) {
int[] arr = {1, 2};
method(arr);
System.out.println(arr[0]); // 1
System.out.println(arr[1]); // 2
}
public static void method(int[] arr) {
arr = new int[]{100, 200};
}
}
最终原数组仍然是:
[1, 2]
因此,更准确的理解是:
Java 永远是值传递。引用类型传递的是引用值的副本,而不是“引用传递”。
十一、方法重载(Overload)
1. 什么是方法重载
在同一个类中:
方法名相同,但是参数列表不同的方法,称为方法重载。
例如:
public static int add(int a, int b) {
return a + b;
}
public static double add(double a, double b) {
return a + b;
}
这两个方法:
- 方法名都叫
add - 参数类型不同
因此构成重载。
2. 参数列表不同的情况
2.1 参数个数不同
public static void method(int a) {
}
public static void method(int a, int b) {
}
构成重载。
2.2 参数类型不同
public static void method(int a) {
}
public static void method(double a) {
}
构成重载。
2.3 参数类型顺序不同
public static void method(int a, double b) {
}
public static void method(double a, int b) {
}
构成重载。
3. 与重载无关的因素
3.1 与参数名无关
下面两个方法:
public static void method(int a) {
}
public static void method(int b) {
}
不构成重载。
因为:
int a
和:
int b
参数类型完全相同。
参数名不同没有意义。
实际上,这样写会直接发生重复定义错误。
3.2 与返回值类型无关
下面两个方法:
public static int method(int a) {
return 1;
}
public static double method(int a) {
return 1.0;
}
不构成重载。
虽然返回值类型不同:
int
double
但是参数列表完全相同,因此 Java 无法仅根据返回值判断应该调用哪个方法。
4. 判断方法重载的核心
判断两个方法是否构成重载,主要看:
方法名是否相同
+
参数列表是否不同
参数列表不同包括:
1. 参数个数不同
2. 参数类型不同
3. 参数类型顺序不同
与下面这些内容无关:
1. 参数名称
2. 返回值类型
十二、本节总结
本节主要学习了 Java 中三个非常重要的知识模块。
1. 流程控制
分支语句:
if
switch
循环语句:
for
while
其中:
if适合复杂条件判断switch适合多个固定值匹配for适合循环次数较明确的场景while适合循环次数不明确、主要依靠条件结束的场景
2. 数组
数组用于一次存储多个相同类型的数据。
常见定义:
int[] arr = new int[3];
或者:
int[] arr = {1, 2, 3};
访问元素:
arr[0]
获取长度:
arr.length
遍历数组:
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
3. 方法
方法用于封装一个独立功能。
基本格式:
public static 返回值类型 方法名(参数列表) {
方法体;
}
Java 参数传递的本质:
始终是值传递
基本类型:
传递具体值的副本
引用类型:
传递引用值的副本
方法重载要求:
方法名相同,参数列表不同
掌握这些知识后,就已经可以开始编写结构更加完整、逻辑更加清晰的 Java 程序了。
更多推荐

所有评论(0)