主题
Java数组完全指南:定义、操作与内存分析
一、核心知识点
1. 数组概述
定义:数组是一个容器,本身属于引用类型
作用:一次存储多个数据
特点:
- 定长:定义数组时长度确定,后续不能更改
- 既能存储基本类型,也能存储引用类型的数据
2. 数组的定义方式
2.1 动态初始化
java
数据类型[] 数组名 = new 数据类型[数组长度];
数据类型 数组名[] = new 数据类型[数组长度];格式说明:
- 等号左边的数据类型:规定数组中元素的类型
[]:代表数组- 数组名:见名知意
new:创建数组- new后面的数据类型:要和等号左边的数据类型一致
[数组长度]:给数组规定长度,最多能存多少个数据
2.2 静态初始化
java
数据类型[] 数组名 = new 数据类型[]{元素1,元素2...};
数据类型 数组名[] = new 数据类型[]{元素1,元素2...};2.3 简化静态初始化(最常用)
java
数据类型[] 数组名 = {元素1,元素2...};代码示例:
java
public class Demo01Array {
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 = {"努尔哈赤","皇太极","顺治","康熙","雍正","乾隆","嘉庆","道光","咸丰","同治","光绪","宣统"};
}
}3. 数组的基本操作
3.1 获取数组长度
java
数组名.length注意:数组中的length是一个属性,不是方法
java
public class Demo02Array {
public static void main(String[] args) {
int[] arr = {2,21,23,341,4,4,3,3,5,65,67,7,7};
System.out.println(arr.length);
}
}3.2 索引
概述:元素在数组中的位置(编号、下标)
特点:
- 从0开始,最大索引是
数组长度-1 - 索引是唯一的
3.3 存储元素
java
数组名[索引值] = 元素;java
public class Demo03Array {
public static void main(String[] args) {
int[] arr = new int[3];
arr[0] = 100;
arr[1] = 200;
arr[2] = 300;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
}
}3.4 获取元素
java
数组名[索引值]注意:
- 数组不能直接输出数组名,因为直接输出数组名会输出数组在内存中的地址值
- 地址值:引用类型数据在内存中保存的唯一编号

3.5 遍历数组
概述:挨个将数组中的元素获取出来
快捷键:数组名.fori
java
public class Demo05Array {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}4. 动态初始化与静态初始化的区别
| 对比项 | 动态初始化 | 静态初始化 |
|---|---|---|
| 定义时 | 只指定元素类型和长度 | 直接存储具体值 |
| 默认值 | 有默认值 | 根据存储的数据确定长度 |
| 使用场景 | 知道元素类型和个数,但不知道具体存什么 | 定义时就知道存什么 |
各类型默认值:
| 数据类型 | 默认值 |
|---|---|
| 整数 | 0 |
| 小数 | 0.0 |
| 字符 | '\u0000'(空白字符) |
| 布尔 | false |
| 引用类型 | null |
5. 数组常见异常
5.1 数组索引越界异常
异常名称:ArrayIndexOutOfBoundsException
出现原因:操作的索引超出了数组的索引范围

5.2 空指针异常
异常名称:NullPointerException
出现原因:如果一个引用类型为null,再操作这个引用类型数据,就会出现空指针异常
java
public class Demo07Array {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr.length);
arr = null;
System.out.println(arr.length);
}
}
6. 内存分析
6.1 Java内存划分
| 内存区域 | 作用 |
|---|---|
| 堆(Heap) | 保存引用类型的数据,每new一次就开辟一个空间,自动分配地址值 |
| 栈(Stack) | 运行方法,方法的运行都会进栈运行 |
| 方法区(Method Area) | 保存类的信息以及类中成员的信息 |
| 本地方法栈(Native Method Stack) | 运行本地方法(带native关键字的方法) |
| 寄存器(PC Register) | 和CPU有关 |

6.2 一个数组内存图

6.3 两个数组内存图
创建两个数组时产生了不同的空间,修改一个空间中的数据不会影响另外一个空间的数据。

6.4 两个数组指向同一片内存空间
arr2不是重新创建出来的,而是arr直接赋值过去的,此时arr和arr2指向同一片空间,操作同一个数组。

7. 数组扩容
数组定义后长度不能改变,所谓的"扩容"实际上是创建一个更大的新数组,将原数组元素复制过去。
java
public class Demo04Array {
public static void main(String[] args) {
int[] arr1 = {1,2,3};
int[] arr2 = new int[5];
for (int i = 0; i < arr1.length; i++) {
arr2[i] = arr1[i];
}
arr1 = arr2;
for (int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]);
}
}
}
二、常见面试题
1. 数组的特点是什么?⭐
答案:
- 定长:数组一旦创建,长度不能改变
- 可以存储基本类型和引用类型
- 数组本身是引用类型
- 数组元素在内存中是连续存储的
- 通过索引访问元素,效率高
2. 动态初始化和静态初始化有什么区别?⭐⭐
答案:
| 对比项 | 动态初始化 | 静态初始化 |
|---|---|---|
| 定义方式 | new 数据类型[长度] | {元素1,元素2...} |
| 元素值 | 使用默认值 | 直接指定具体值 |
| 使用场景 | 只知道元素个数,不知道具体值 | 定义时就知道具体值 |
3. 数组索引越界异常是什么原因造成的?如何避免?⭐⭐
答案:
- 原因:访问的索引超出了数组的有效索引范围(0 到 length-1)
- 避免方法:
- 在访问前检查索引是否在有效范围内
- 使用增强for循环遍历
- 使用
数组名.length获取长度进行边界判断
4. 什么是空指针异常?在数组操作中什么情况会出现?⭐⭐
答案:
- 定义:当引用类型变量为null时,尝试调用其方法或访问其属性,就会抛出NullPointerException
- 数组中出现的情况:
- 数组引用被赋值为null后,继续访问数组元素或属性
- 数组元素为引用类型且为null时,调用该元素的方法
5. 数组在内存中是如何存储的?⭐⭐⭐
答案:
- 数组是引用类型,数组引用变量存储在栈中
- 数组元素存储在堆中
- 数组引用变量存储的是堆中数组的首地址
- 数组元素在堆中是连续存储的
- 每个数组对象都有一个length属性
6. 如何理解数组的"定长"特性?如果需要动态扩容怎么办?⭐⭐⭐
答案:
- 定长:数组一旦创建,其长度就固定不变
- 扩容方案:
- 创建一个更大的新数组
- 将原数组元素复制到新数组
- 将原数组引用指向新数组
- 实际开发中可使用
Arrays.copyOf()或System.arraycopy()
7. 数组的默认值是什么?⭐
答案:
| 数据类型 | 默认值 |
|---|---|
| byte, short, int, long | 0 |
| float, double | 0.0 |
| char | '\u0000' |
| boolean | false |
| 引用类型(类、接口、数组) | null |
8. 以下代码输出结果是什么?⭐⭐
java
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1;
arr2[0] = 100;
System.out.println(arr1[0]);答案:输出 100
解析:arr2 = arr1 是将arr1的地址值赋给arr2,两个引用指向同一个数组对象,修改arr2的元素会影响arr1。
三、实用代码片段
1. 获取数组最大值
java
public class Demo01GetMax {
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
System.out.println("最大值:" + max);
}
}2. 统计符合条件的元素个数
java
import java.util.Random;
public class Demo02Count {
public static void main(String[] args) {
int[] arr = new int[10];
Random rd = new Random();
int count = 0;
for (int i = 0; i < arr.length; i++) {
arr[i] = rd.nextInt(101);
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 3 == 0 && arr[i] % 5 == 0 && arr[i] % 7 != 0) {
count++;
}
}
System.out.println("符合条件的个数:" + count);
}
}3. 格式化输出数组
java
public class Demo03Print {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4};
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i] + "]");
} else {
System.out.print(arr[i] + ", ");
}
}
}
}输出:[1, 2, 3, 4]
4. 查找元素索引
java
import java.util.Scanner;
public class Demo04Search {
public static void main(String[] args) {
int[] arr = {11, 22, 33, 44, 55, 66};
Scanner sc = new Scanner(System.in);
int data = sc.nextInt();
int flag = 0;
for (int i = 0; i < arr.length; i++) {
if (data == arr[i]) {
System.out.println("找到元素,索引为:" + i);
flag++;
}
}
if (flag == 0) {
System.out.println(-1);
}
}
}5. 数组扩容模板
java
public class ArrayExpand {
public static void main(String[] args) {
int[] oldArr = {1, 2, 3};
int newLength = oldArr.length * 2;
int[] newArr = new int[newLength];
for (int i = 0; i < oldArr.length; i++) {
newArr[i] = oldArr[i];
}
oldArr = newArr;
}
}四、经典练习题
练习1:获取数组最大值(基础题)
题目:定义一个数组,存储若干整数,找出最大值。
思路:
- 定义数组,存储数据
- 定义变量max,初始值为数组第一个元素
- 遍历数组,比较每个元素与max
- 如果元素大于max,更新max
- 输出max
参考代码:
java
public class GetMax {
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
System.out.println(max);
}
}练习2:统计符合条件的元素(进阶题)
题目:随机产生10个[0,100]之间整数,统计既是3又是5,但不是7的倍数的个数。
思路:
- 创建长度为10的数组和Random对象
- 产生10个随机数放入数组
- 遍历数组,判断条件:
num % 3 == 0 && num % 5 == 0 && num % 7 != 0 - 符合条件则计数器加1
参考代码:
java
import java.util.Random;
public class CountNumbers {
public static void main(String[] args) {
int[] arr = new int[10];
Random rd = new Random();
int count = 0;
for (int i = 0; i < arr.length; i++) {
arr[i] = rd.nextInt(101);
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 3 == 0 && arr[i] % 5 == 0 && arr[i] % 7 != 0) {
count++;
}
}
System.out.println(count);
}
}练习3:格式化输出数组(进阶题)
题目:定义数组 int[] arr = {1,2,3,4},遍历输出为 [1,2,3,4] 格式。
思路:
- 先输出
[ - 遍历数组,输出每个元素
- 如果不是最后一个元素,输出
, - 最后一个元素输出
]
参考代码:
java
public class PrintArray {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4};
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i] + "]");
} else {
System.out.print(arr[i] + ", ");
}
}
}
}练习4:查找元素索引(进阶题)
题目:键盘录入一个整数,找出该整数在数组中的索引位置,找不到返回-1。
思路:
- 定义数组
- 键盘录入要查找的数据
- 遍历数组,比较每个元素
- 找到则输出索引,找不到输出-1
参考代码:
java
import java.util.Scanner;
public class SearchIndex {
public static void main(String[] args) {
int[] arr = {11, 22, 33, 44, 55, 66};
Scanner sc = new Scanner(System.in);
int data = sc.nextInt();
int flag = 0;
for (int i = 0; i < arr.length; i++) {
if (data == arr[i]) {
System.out.println(i);
flag++;
}
}
if (flag == 0) {
System.out.println(-1);
}
}
}练习5:键盘录入学员姓名(综合题)
题目:用一个数组存储本组学员的姓名,从键盘输入,并遍历显示。
思路:
- 创建指定长度的String数组
- 使用Scanner循环录入姓名
- 遍历数组输出所有姓名
参考代码:
java
import java.util.Scanner;
public class StudentNames {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入学员人数:");
int count = sc.nextInt();
String[] names = new String[count];
for (int i = 0; i < names.length; i++) {
System.out.print("请输入第" + (i + 1) + "个学员姓名:");
names[i] = sc.next();
}
System.out.println("\n学员名单:");
for (int i = 0; i < names.length; i++) {
System.out.println((i + 1) + ". " + names[i]);
}
}
}五、学习建议
1. 学习重点
- 理解数组的本质:数组是引用类型,存储在堆内存中
- 掌握索引操作:索引从0开始,最大索引是length-1
- 理解内存模型:理解栈和堆的关系,理解地址值的概念
- 避免常见异常:索引越界和空指针是数组操作最常见的异常
2. 编程技巧
- 使用
数组名.fori快速生成遍历代码 - 访问数组元素前,先检查索引是否有效
- 操作引用类型数组元素前,先判断是否为null
- 需要动态扩容时,考虑使用ArrayList等集合类
3. 调试技巧
- 直接打印数组名会输出地址值,应遍历打印元素
- 使用IDE的调试功能查看数组内容
- 遇到异常时,检查索引范围和null值
4. 扩展方向
[基于课程进度补充] 学习完数组后,建议继续学习:
- 二维数组
- Arrays工具类
- ArrayList集合(动态数组)
- 数组排序算法(冒泡、选择等)
- 数组查找算法(二分查找)
六、知识图谱
∂dJava数组
├── 基础概念
│ ├── 定义:引用类型容器
│ ├── 特点:定长、连续存储
│ └── 作用:存储多个同类型数据
│
├── 初始化方式
│ ├── 动态初始化:new 数据类型[长度]
│ └── 静态初始化:{元素1, 元素2, ...}
│
├── 基本操作
│ ├── 获取长度:数组名.length
│ ├── 索引访问:从0开始
│ ├── 存储元素:数组名[索引] = 值
│ ├── 获取元素:数组名[索引]
│ └── 遍历:for循环
│
├── 常见异常
│ ├── ArrayIndexOutOfBoundsException
│ └── NullPointerException
│
├── 内存分析
│ ├── 栈:存储引用变量
│ ├── 堆:存储数组对象
│ └── 地址值:引用指向对象
│
└── 高级操作
├── 数组扩容
├── 查找元素
└── 统计计算七、速查表
数组定义速查
| 方式 | 语法 | 示例 |
|---|---|---|
| 动态初始化 | 数据类型[] 数组名 = new 数据类型[长度]; | int[] arr = new int[5]; |
| 静态初始化 | 数据类型[] 数组名 = {元素...}; | int[] arr = {1, 2, 3}; |
数组操作速查
| 操作 | 语法 | 示例 |
|---|---|---|
| 获取长度 | 数组名.length | arr.length |
| 存储元素 | 数组名[索引] = 值; | arr[0] = 100; |
| 获取元素 | 数组名[索引] | int num = arr[0]; |
| 遍历数组 | for (int i = 0; i < arr.length; i++) | 见代码示例 |
默认值速查
| 数据类型 | 默认值 |
|---|---|
| byte, short, int, long | 0 |
| float, double | 0.0 |
| char | '\u0000' |
| boolean | false |
| 引用类型 | null |