2.7 数组
数组 = 一排带编号的同类型格子,一个名字管全部。编号(索引)从 0 开始;配着 循环 使用,"对每个格子做同一件事"从此只要三行。
前置知识:2.2 Java中的变量(格子思想)、2.5 循环结构语句(遍历靠它)、2.6 方法(数组能整包传进方法)。
1. 为什么需要数组
记全班 40 人的成绩,不用数组得写 40 个变量:score1、score2……命名累、求和更没法写(总不能手写 40 个加号)。数组开一排格子共用一个名字,用编号区分——配合循环,40 个格子统一处理只要三行。
2. 定义与初始化:两种开法
// ① 动态初始化:先定死格数,后填内容(没填的格子有默认值)
int[] scores = new int[5]; // 5 个格子,全是默认值 0
scores[0] = 90;
scores[1] = 85;
// ② 静态初始化:开格子的同时就把数据放进去(格数自动算出来)
int[] arr = {90, 85, 77, 92, 60};
动态初始化的默认值(没填也大概率猜得到,考试常考):
| 类型 | 默认值 |
|---|---|
| int / byte / short / long | 0 |
| double / float | 0.0 |
| boolean | false |
| char | '\u0000'(空白字符) |
| String 等引用类型 | null("什么都没有") |
一开始就知道装什么 → 静态 {90, 85, ...};先知道要几个格子、数据后面再填(比如等着用户输入)→ 动态 new int[5]。
3. 访问与赋值:靠编号
int[] arr = {90, 85, 77, 92, 60};
System.out.println(arr[0]); // 90 —— 第 1 个,编号 0
System.out.println(arr[2]); // 77 —— 第 3 个,编号 2
arr[4] = 95; // 把最后一格的 60 改成 95
数组三个刻在骨头上的规则:
- 编号从 0 开始:第 1 个是
arr[0],第 n 个是arr[n-1](上面那张图) arr.length是格数(是个变量不是方法,不加括号):5 个格子 length = 5,最大编号 4- 越界必炸:
arr[5]编译能过、运行时报ArrayIndexOutOfBoundsException——5 个格子的最大编号是 4
变量 arr 本身不住数据——它存在栈里,存的是"这一排格子住在堆里哪"的地址(1.4 提过堆和栈,这里终于见到了)。所以 arr 传给别人时传的是地址,不是复制一整排数据——这个细节第五章面向对象还会回头讲。
4. 遍历:数组 + 循环 = 天生一对
int[] arr = {90, 85, 77, 92, 60};
for (int i = 0; i < arr.length; i++) { // 注意是 <,不是 <=
System.out.println("第" + (i + 1) + "个:" + arr[i]);
}
固定三件套:i 从 0 起、i < arr.length(不越界)、arr[i] 取值。这个模板会写,数组的日常就拿下了一半。
5. 三个经典算法(数组的"会做三件事")
// ① 求和(2.5 的累加器搬过来)
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
System.out.println("总分:" + sum); // 404
// ② 求最大值(擂台赛:第一个先站上擂台,后面挨个挑战)
int max = arr[0];
for (int i = 1; i < arr.length; i++) { // 从 1 开始,0 号已经在擂台上
if (arr[i] > max) {
max = arr[i];
}
}
System.out.println("最高分:" + max); // 92
// ③ 逆序输出(倒着走一遍)
for (int i = arr.length - 1; i >= 0; i--) {
System.out.println(arr[i]);
}
求最大值的擂台思路比代码本身值钱:设 max = arr[0](不是 0!全负数的数组会出错),逐个比、谁大谁上擂台。
6. 数组传进方法:整包带走
public static int total(int[] nums) { // 形参写"类型[] 名字"
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
return sum;
}
// 调用:int s = total(arr); —— 一整个数组整包传进去
2.6 说"传参是复制"对数组也成立——但复制的是地址,方法里改 nums[0],外面的 arr[0] 真的会变(拿到的是同一排格子的钥匙)。这和 2.6 的 int 传值不一样,先记住现象,原理第五章收网。
7. 动手:Demo08 三件事全做一遍
第 1 步:IDEA02 项目 → src → New → Java Class → Demo08,psvm 生成主方法。
第 2 步:抄入:
public class Demo08 {
public static void main(String[] args) {
int[] arr = {90, 85, 77, 92, 60};
int sum = 0;
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
System.out.println("arr[" + i + "] = " + arr[i]);
sum += arr[i];
if (arr[i] > max) {
max = arr[i];
}
}
System.out.println("总分:" + sum); // 404
System.out.println("最高分:" + max); // 92
}
}
第 3 步:绿三角 ▶ 运行,核对。
第 4 步(两个 30 秒实验):
- 把
i < arr.length改成i <= arr.length——跑一次,亲眼看越界异常长什么样(然后改回来)。见过一次,以后报这个错三秒定位 - 把
arr换成new int[5]再打印——看 5 个 0(动态初始化的默认值)
8. 常见误区小结
从 0 开始。{90, 85, 77} 的 90 是 arr[0]。5 个格子的最大编号是 4,不是 5。
arr.length 是变量(不加括号);arr.length() 是方法写法——数组不这么用,混了直接编译错。String 的 length() 才是方法,别记串。
最后一圈拿 arr[length] 越界,运行时炸。条件永远是 <。
数据全是负数时结果是错的 0。正确姿势 max = arr[0],从擂台上已有的选手开始比。
int[] arr = new int[5]{1,2,3,4,5}; 非法——new 带了格数就不能再列数据。要么 new int[5] 空着填,要么 {...} 直接口袋装满。
9. 自测题
arr[1] 是 20(编号 1 = 第 2 个);arr[arr.length - 1] = arr[3] = 40(length 是 4,减 1 正好是最后一个)——"取最后一格"的万能写法,背下来。
double:0.0 三个;boolean:false;String:null(不是空字符串 ""——null 是"格子根本没指向任何东西",调它的方法会炸 NullPointerException)。
数据可能全是负数(如 {-5, -2, -9}):用 0 起步,谁都"大不过"0,答案错成 0;用 arr[0] 起步,比的一直是数组里的真成员,永远正确。
编译能过、运行炸:ArrayIndexOutOfBoundsException。编译器只查语法,不查编号超没超(编号可以是变量,它算不过来);运行到这行才真去摸内存,摸空了就报错。
会变——和 int 不一样。int 传的是值的复制(两套格子),数组传的是地址的复制(两把同一排格子的钥匙),改的是同一个堆里的数据。原理(引用类型)第五章收网,先记住现象。
10. 下一步学什么
- ☐ 2.8 本章小结 —— 七节串成一条线:概念速查表、代码模板速查、八大名坑、毕业大题(方法 + 循环 + 数组 + 选择一题全串)
- ☐ 动手作业:
Demo08跑通 + 越界实验(必须亲眼炸一次)
11. 相关笔记
- 2.5 循环结构语句 ← 遍历是数组的第一生产力
- 2.6 方法 ← 数组整包传参、方法复用
- 1.4 Java程序的运行机制 ← 栈/堆在这里正式见面
- 📇 Java基础 · 索引
- 🏠 返回主页