【Java从入门到大牛】数组详解 缺乏、安全感 2024-04-26 02:38 83阅读 0赞 > ? 本文由 [程序喵正在路上][Link 1] 原创,CSDN首发! > ? 系列专栏:[Java从入门到大牛][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}; ![在这里插入图片描述][1f66fe02168649e99aff5429e882022a.png] * 数组变量名中存储的是数组在内存中的地址,数组是一种引用数据类型 * 数组中存储的元素都有一个下标,从 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]; ![在这里插入图片描述][ec2c6739ce214447953ac7d31933ae7d.png] **动态初始化数组元素默认值规则:** <table> <thead> <tr> <th>数据类型</th> <th>明细</th> <th>默认值</th> </tr> </thead> <tbody> <tr> <td>基本类型</td> <td>byte、short、char、int、long</td> <td>0</td> </tr> <tr> <td>基本类型</td> <td>float、double</td> <td>0.0</td> </tr> <tr> <td>基本类型</td> <td>boolean</td> <td>false</td> </tr> <tr> <td>引用类型</td> <td>类、接口、数组、<font>String</font></td> <td>null</td> </tr> </tbody> </table> ### 案例:评委打分 ### **需求** 某歌唱比赛,需要开发一个系统:可以录入 6 名评委的打分,录入完毕后立即输出平均分作为选手的得分 **分析** 1. 6 名评委的打分是后期录入的,一开始不知道具体的分数,因此定义一个动态初始化的数组存分数 2. 遍历数组中的每个位置,每次提示用户录入一个评委的分数,并存入到数组对应的位置 3. 遍历数组中的每个元素进行求和,最终算出平均分打印出来即可 **代码示例** 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); } } **运行结果** ![在这里插入图片描述][271c6cd530a94964af17ddf718cc1258.png] ## 数组在计算机中的执行原理 ## ### 数组的执行原理和Java程序的执行原理 ### **Java 内存分配介绍** * 方法区 * 栈 * 堆 * 本地方法栈 * 寄存器 ![在这里插入图片描述][02fcb16192f841e4a92a5033977dbcd2.png] **数组在计算机中的执行原理** 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]); } } **运行结果** ![在这里插入图片描述][bca79d297de94031b32e6cf1b14e3b84.png] **具体原理**![在这里插入图片描述][b686b8906fa24f58bc2d2654fcf018cf.png] **总结** 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]); } } **运行结果** ![在这里插入图片描述][adf6b2b42c1b443b918ffc5da191fa53.png] **具体原理** ![在这里插入图片描述][97b46535b09140039f85629a865ffd35.png] **使用数组时常见的一个问题** 如果某个数组变量存储的地址是 null,那么该变量将不再指向任何数组对象 arr2 = null; //把null赋值给arr2 System.out.println(arr2); //null System.out.println(arr2[0]); //会出异常 System.out.println(arr2.length); //会出异常 ![在这里插入图片描述][4f57e66305d645409a8c5b54a31cbb9f.png] **总结** 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(); } } **运行结果** ![在这里插入图片描述][92f7b98ae5f24a938ba196d631fd2f62.png] **总结** 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(); } } **运行结果** ![在这里插入图片描述][e584880951bb4b1faefdb5ec5540d62c.png] ## 补充知识:Debug工具的使用 ## **什么是 Debug 工具 ?** IDEA 自带的断点调试工具,可以控制代码从断点开始一行一行地执行,然后详细观看程序执行的情况 **Debug 工具基本使用步骤** 1. 在需要调试的代码行左侧,点击一下,形成一个红色的断点 2. 在运行的时候选择使用 Debug 方式启动程序,启动后程序会在运行到断点处时暂停 3. 点击对应按钮控制代码一行一行地往下执行 ![在这里插入图片描述][630dd3e7895b4fcbb63e1a9d07b42f09.png] [Link 1]: https://blog.csdn.net/weixin_62511863?spm=1011.2421.3001.5343 [Java]: https://blog.csdn.net/weixin_62511863/category_12365679.html?spm=1001.2014.3001.5482 [1f66fe02168649e99aff5429e882022a.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/799472671c274312b031f3c2fe3e7007.png [ec2c6739ce214447953ac7d31933ae7d.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/06911308aab747388e40b01e9ee86c63.png [271c6cd530a94964af17ddf718cc1258.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/b6088f30e56947f2885a0b31b43396cc.png [02fcb16192f841e4a92a5033977dbcd2.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/b5d7c25b1303424cad62e337a41cf244.png [bca79d297de94031b32e6cf1b14e3b84.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/0cb850afc41b46f58b33cec05148d80d.png [b686b8906fa24f58bc2d2654fcf018cf.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/b6256528991b4d558ccf11842f8d4ff9.png [adf6b2b42c1b443b918ffc5da191fa53.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/760db776dd5a4070beb600a7bfd5a196.png [97b46535b09140039f85629a865ffd35.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/7b0bbd015c664603b730a947e3176c4d.png [4f57e66305d645409a8c5b54a31cbb9f.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/659b166cdd3c42aa9078893c9669e9c4.png [92f7b98ae5f24a938ba196d631fd2f62.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/d7582773f26640d1962a5bef48ca1cec.png [e584880951bb4b1faefdb5ec5540d62c.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/cad7facb7e194cafa7d6001e32e5d917.png [630dd3e7895b4fcbb63e1a9d07b42f09.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/75d5b0daea7a4bdc9b1e96f14ede8b13.png
相关 【Java从入门到大牛】Java高级技术 注解(Annotation)就是 Java 代码里的特殊标记,比如:@Override、@Test 等,作用是:让其他程序根据注解信息来决定怎么执行该程序自定义注解,就是... 忘是亡心i/ 2024年04月26日 02:57/ 0 赞/ 75 阅读
相关 【Java从入门到大牛】多线程 什么是线程安全问题?多个线程,同时操作同一个共享资源的时候,可能会出现业务安全问题取钱的线程安全问题场景:小明和小红是一对夫妻,他们有一个共同的账户,余额是10万元,如果... 谁借莪1个温暖的怀抱¢/ 2024年04月26日 02:55/ 0 赞/ 66 阅读
相关 【Java从入门到大牛】编程思维训练 本文讲解了几个小案例,巩固了之前学习Java的一些基础知识,同时积累了一定的代码量 本是古典 何须时尚/ 2024年04月26日 02:40/ 0 赞/ 74 阅读
还没有评论,来说两句吧...