🔥 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:Java从入门到大牛
🌠 首发时间:2023年7月9日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾
🌟 一以贯之的努力 不得懈怠的人生
目录
- 什么是数组
- 数组的定义和访问
- 静态初始化数组
- 静态初始化数组在计算机中的基本原理
- 数组的访问
- 数组的遍历
- 动态初始化数组
- 静态初始化数组在计算机中的基本原理
- 案例:评委打分
- 数组在计算机中的执行原理
- 数组的执行原理和Java程序的执行原理
- 多个变量指向同一个数组的问题
- 专项训练:数组常见案例
- 数组求最值
- 数组反转
- 随机排名
- 补充知识:Debug工具的使用
什么是数组
数组就是一个容器,用来存储一批相同类型的数据
举例
int[] arr = {1, 2, 3, 4, 5};
String[] names = {"张三", "李四", "王五"};
有了变量,为什么还要用数组 ?
从上面的例子中,我们很容易就可以看出来,如果使用变量来存储一系列相同类型的数据,那么代码就会很繁琐;而使用数组则代码简洁,逻辑清晰
数组的定义和访问
静态初始化数组
什么是静态初始化数组 ?
在定义数组的时候直接给数组赋值
静态初始化数组的格式
// 完整格式
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元素3, ...};
int[] ages = new int[]{12, 34, 56};
double[] scores = new double[]{1.11, 2.22, 3.33};
// 简化格式
数据类型[] 数组名 = {元素1, 元素2, 元素3, ...};
int[] ages = {12, 34, 56};
适用业务场景
静态初始化适合一开始就知道要存入哪些元素值的业务场景
注意事项
- “
数据类型[] 数组名
” 也可以写成 “数据类型 数组名[]
” - 什么类型的数组只能存放什么类型的数组
静态初始化数组在计算机中的基本原理
int[] ages = {12, 24, 36};
- 数组变量名中存储的是数组在内存中的地址,数组是一种引用数据类型
- 数组中存储的元素都有一个下标,从 0 开始
数组的访问
怎么访问数组 ?
数组名[索引]
举例
// 取值
System.out.println(arr[0]);
// 赋值
arr[2] = 100;
System.out.println(arr[2]);
数组有一个长度属性:length
// 获取数组的长度(就是数组中的元素个数)
System.out.println(arr.length);
数组的最大索引可以怎么表示 ?
数组名.length-1 //前提是元素个数大于0
注意事项
访问数组时,使用的索引不能超过数组的最大索引。当访问越界时,执行程序时会出 bug,会出现一个索引越界的异常提示
数组的遍历
什么是遍历 ?
遍历就是从头到尾一个一个地访问数据
为什么要遍历数组 ?
有时候,我们要对一个数组进行求和、搜索元素、找最大值或最小值的时候,就需要遍历数组
如何遍历数组 ?
int[] ages = {20, 30, 40, 50};
for (int i = 0; i < ages.length; i++) {
System.out.println(ages[i]);
}
动态初始化数组
什么是动态初始化数组 ?
定义数组时先不存入具体的元素值,只确定数组存储的数据类型和数组的长度
动态初始化数组的格式
数据类型[] 数组名 = new 数据类型[长度];
int[] arr = new int[3];
// 后赋值
arr[0] = 10;
System.out.println(arr[0]);
适用业务场景
动态初始化适合开始不确定具体元素值,只知道元素个数的业务场景
注意事项
静态初始化和动态初始化数组的写法是独立的,不可以混用,即 int[] arr = new int[3]{30,40,50};
静态初始化数组在计算机中的基本原理
int[] arr = new int[3];
动态初始化数组元素默认值规则:
数据类型 | 明细 | 默认值 |
---|---|---|
基本类型 | byte、short、char、int、long | 0 |
基本类型 | float、double | 0.0 |
基本类型 | boolean | false |
引用类型 | 类、接口、数组、String | null |
案例:评委打分
需求
某歌唱比赛,需要开发一个系统:可以录入 6 名评委的打分,录入完毕后立即输出平均分作为选手的得分
分析
- 6 名评委的打分是后期录入的,一开始不知道具体的分数,因此定义一个动态初始化的数组存分数
- 遍历数组中的每个位置,每次提示用户录入一个评委的分数,并存入到数组对应的位置
- 遍历数组中的每个元素进行求和,最终算出平均分打印出来即可
代码示例
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double[] scores = new double[6];
double sumScore = 0, averScore = 0; // 总分、平均分, 记得初始化变量
// 录入分数
for (int i = 0; i < scores.length; i++) {
System.out.println("请输入一个评委的分数:");
scores[i] = sc.nextDouble();
}
// 计算总分
for (int i = 0; i < scores.length; i++) {
sumScore += scores[i];
}
// 计算平均分
averScore = sumScore / scores.length;
System.out.println("选手的得分为:" + averScore);
}
}
运行结果
数组在计算机中的执行原理
数组的执行原理和Java程序的执行原理
Java 内存分配介绍
- 方法区
- 栈
- 堆
- 本地方法栈
- 寄存器
数组在计算机中的执行原理
public class ArrayDemo {
public static void main(String[] args) {
int a = 10;
System.out.println(a);
int[] arr = {11, 22, 33};
System.out.println(arr);
System.out.println(arr[1]);
arr[0] = 44;
arr[1] = 55;
arr[2] = 66;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
}
}
运行结果
具体原理
总结
1、运行一个 Java 程序,主要看 JVM 中包含的哪几部分内存区域 ?
- 方法区
- 栈内存
- 堆内存
2、简单说说 int a = 20; int[] arr = new int[3];
这两行代码的执行原理 ?
- a 是变量,直接放在栈中, a 变量中存储的数据就是 20 这个值
new int[3]
是创建一个数组对象,会在堆内存中开辟区域存储 3 个整数- arr 是变量,在栈中,arr 中存储的是数组对象在堆内存中的地址值
多个变量指向同一个数组的问题
多个变量指向同一个数组
public class ArrayDemo2 {
public static void main(String[] args) {
int[] arr1 = {11, 22, 33};
int[] arr2 = arr1;
System.out.println(arr1);
System.out.println(arr2);
arr2[1] = 99;
System.out.println(arr1[1]);
}
}
运行结果
具体原理
使用数组时常见的一个问题
如果某个数组变量存储的地址是 null,那么该变量将不再指向任何数组对象
arr2 = null; //把null赋值给arr2
System.out.println(arr2); //null
System.out.println(arr2[0]); //会出异常
System.out.println(arr2.length); //会出异常
总结
1、多个数组变量,指向同一个数组对象的原因是什么 ?需要注意什么 ?
- 多个数组变量中存储的是同一个数组对象的地址
- 多个变量修改的都是同一个数组对象中的数据
2、如果某个数组变量中存储的 null,代表什么意思 ?需要注意什么 ?
- 代表这个数组变量没有指向数组对象
- 可以输出这个变量,但是不能用这个数组变量去访问数据或者访问数组长度,会报空指针异常:NullPointerException
专项训练:数组常见案例
数组求最值
实现步骤
- 把数据拿到程序中去,用数组装起来
- 定义一个变量 max 用于记录最终的最大值,建议存储数组的第一个元素值来作为参照值
- 从第二个位置开始遍历数组的数据,如果遍历的当前数据大于 max 变量存储的数据,则替换变量存储的数据为当前数据
- 循环结束后输出 max 变量即可
代码示例
public class Test {
public static void main(String[] args) {
int[] scores = {34, 98, 29, 78, 0, -43};
int max = scores[0];
// 逐个比较数据
for (int i = 1; i < scores.length; i++) {
if (scores[i] > max) {
max = scores[i];
}
}
System.out.println("最大值为: " + max);
}
}
数组反转
需求
某个数组有 5 个数据:10、20、30、40、50,请将这个数组中的数据进行反转
分析
数据的反转操作实际上就是:依次前后交换数据即可实现
代码示例
public class Test {
public static void main(String[] args) {
int[] digits = {10, 20, 30, 40, 50};
System.out.println("反转前的数组: ");
for (int i = 0; i < digits.length; i++) {
System.out.print(digits[i] + " ");
}
System.out.println();
for (int i = 0; i < digits.length - 1 - i; i++) {
int j = digits.length - 1 - i; // 右边元素的下标
// 交换左右元素
int temp = digits[i];
digits[i] = digits[j];
digits[j] = temp;
}
System.out.println("反转后的数组: ");
for (int i = 0; i < digits.length; i++) {
System.out.print(digits[i] + " ");
}
System.out.println();
}
}
运行结果
总结
1、我们是如何完成数组的反转的 ?
使用 for 循环,控制让数组的前后位置的元素,依次交换
2、数组如何实现前后元素交换 ?
- 定义一个临时变量记住前一个位置处的元素值
- 再把后一个位置处的元素值赋值给前一个位置处
- 最后把临时变量记住的前一个位置的元素值赋值给后一个位置处
随机排名
需求
某公司开发部有 5 名开发人员,要进行项目进展汇报演讲,现在采取随机排名后进行汇报。请先依次录入 5 名员工的工号,然后展示出一组随机的排名顺序
分析
- 定义一个动态初始化的数组用于录入员工的工号
- 遍历数组中的每个元素
- 每遍历到一个数据,都随机生成一个索引值,然后让当前数据与随机生成的索引位置处的数据进行交换
- 输出数组中的内容即可
代码示例
import java.util.Random;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] nums = new int[5];
// 录入工号
for (int i = 0; i < nums.length; i++) {
System.out.print("请输入第" + (i + 1) + "个工号: ");
nums[i] = sc.nextInt();
}
// 随机交换元素
Random r = new Random();
for (int i = 0; i < nums.length; i++) {
int index = r.nextInt(nums.length);
// 交换元素
int temp = nums[i];
nums[i] = nums[index];
nums[index] = temp;
}
// 输出随机排名
System.out.println("随机排名后的一个序列: ");
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
System.out.println();
}
}
运行结果
补充知识:Debug工具的使用
什么是 Debug 工具 ?
IDEA 自带的断点调试工具,可以控制代码从断点开始一行一行地执行,然后详细观看程序执行的情况
Debug 工具基本使用步骤
- 在需要调试的代码行左侧,点击一下,形成一个红色的断点
- 在运行的时候选择使用 Debug 方式启动程序,启动后程序会在运行到断点处时暂停
- 点击对应按钮控制代码一行一行地往下执行