Java基础快速入门:数组概念、定义格式与动态初始化详解

本文纲要

  1. 数组介绍
  2. 数组定义格式
  3. 数组动态初始化
  4. 数组元素访问
  5. Java内存分配与数组内存图
  6. 两个数组内存图
  7. 多个数组指向相同内存
  8. 数组静态初始化
  9. 数组操作常见问题
  10. 数组遍历
  11. 数组获取最大值
  12. 数组元素求和
  13. 数组基本查找
  14. 评委打分案例

数组介绍

数组(Array)是一种容器,用来存储同种数据类型的多个值。与普通变量只能存储单个值不同,数组可以一次存储多个同类型数据,并通过索引访问每一个元素。

数组的典型使用场景:当需要操作一组数据时,例如统计多个班级的成绩、存储多个用户输入等,就可以用数组把这组数据整体管理起来,而不是定义大量零散的变量。

数组定义格式

Java中定义数组有两种格式:

// 格式1:数据类型[] 数组名;
int[] arr;
 
// 格式2:数据类型 数组名[];
int arr2[];

格式1使用最普遍,推荐使用。格式2也能定义数组,但较少见。
这两种方式只是定义了一个数组类型的变量,此时还没有实际的数组容器,不能直接使用。

数组动态初始化

1 ) 概念

动态初始化:在创建数组时只指定长度,系统自动为数组元素分配默认值。

2 ) 格式

数据类型[] 数组名 = new 数据类型[数组长度];

示例:

int[] arr = new int[5];   // 可以存储5个int型整数
byte[] bArr = new byte[3]; // 可以存储3个byte型整数

new关键字负责在堆内存中开辟数组空间,并返回内存地址给数组变量。

3 ) 打印数组名

打印数组名时,看到的是内存地址,例如 [I@10f87f48
解读:

  • @:分隔符
  • [:表示数组类型
  • I:表示存储的数据类型(int)
  • 10f87f48:十六进制内存地址

数组元素访问

1 ) 访问格式

数组名[索引]

索引是数组元素在容器中的编号,从0开始,连续递增。例如长度为3的数组,索引为0、1、2。

2 ) 存取操作

  • 取值:arr[0]
  • 存值:arr[0] = 11

动态初始化后,即使没有赋值,元素也能取出,此时取出的都是默认值

不同类型默认值如下:

数组类型默认值
整数类型0
浮点类型0.0
布尔类型false
字符类型空字符(‘\u0000’)
引用类型null

示例代码

int[] arr = new int[3];
System.out.println(arr[0]); // 0
System.out.println(arr[1]); // 0
System.out.println(arr[2]); // 0
 
arr[0] = 11;
arr[1] = 22;
arr[2] = 33;
System.out.println(arr[0]); // 11
System.out.println(arr[1]); // 22
System.out.println(arr[2]); // 33

Java内存分配与数组内存图

Java程序运行时,内存主要划分为以下几块区域:

  • 栈(Stack):方法运行时进入的内存,局部变量存放在这里。
  • 堆(Heap):new出来的内容存放于此,都有地址值。
  • 方法区(Method Area):字节码文件(.class)加载时进入的内存。

1 ) 单数组内存图

以如下代码为例:

int[] arr = new int[3];
arr[0] = 11;
arr[1] = 22;
arr[2] = 33;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);

📒 堆内存 (Heap)

📙 栈内存 (Stack)

📘 方法区 (Method Area)

main 方法栈帧

引用地址

类加载,入栈执行

声明

Demo3.class
main方法字节码

arr 变量
📍 记录地址: 0x001

0x001 → int[3]
数组对象

索引[0] = 11

索引[1] = 22

索引[2] = 33

执行过程:

  1. .class文件加载到方法区,main方法进入栈。
  2. 执行int[] arr = new int[3],在堆中开辟数组空间(地址0x001),长度为3,默认值0。
  3. 地址赋给栈中的arr变量。
  4. 通过索引赋值,修改堆中对应元素的值。
  5. 打印时,arr通过地址找到堆中数组,再按索引取出元素。

两个数组内存图

int[] arr1 = new int[2];
arr1[0] = 11;
arr1[1] = 22;
 
int[] arr2 = new int[3];
arr2[0] = 33;
arr2[1] = 44;
arr2[2] = 55;

🟧 堆 Heap

🟦 栈 Stack

指向

指向

main() 方法

arr1 引用
0x001

arr2 引用
0x002

地址 0x001
int[2]
[0]=11, [1]=22

地址 0x002
int[3]
[0]=33, [1]=44, [2]=55

关键点:每次new都会在堆中开辟一块新的空间,地址不会重复。

多个数组指向相同内存

int[] arr1 = new int[2];
arr1[0] = 11;
arr1[1] = 22;
 
int[] arr2 = arr1;   // 将arr1记录的地址赋给arr2
arr2[0] = 33;
 
System.out.println(arr1[0]); // 33
System.out.println(arr1[1]); // 22
System.out.println(arr2[0]); // 33 
System.out.println(arr2[1]); // 22

堆 Heap

栈 Stack

main() 栈帧

arr1
记录地址 0x001

arr2
记录地址 0x001

0x001
int[2]
[0] = 33
[1] = 22

当两个引用指向同一个数组时,通过任何一个引用修改数组,另一个引用看到的也是修改后的结果。可以把引用想象成“遥控器”,多个遥控器控制同一台电视。

数组静态初始化

静态初始化:在创建数组时直接指定元素的值,系统自动计算长度

完整格式

数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, ...};

简化格式

数据类型[] 数组名 = {元素1, 元素2, ...};

示例:

int[] arr = new int[]{11, 22, 33};
int[] arr2 = {44, 55, 66};

简化格式虽然没有显式写new,但编译器会补齐,实际仍然会在堆中开辟空间。

动态初始化 vs 静态初始化

动态初始化静态初始化
指定数组长度元素的具体值
系统计算默认值数组长度
适用场景只明确元素个数,不明确具体值(如键盘录入)已经明确要操作的具体数据

数组操作常见问题

1 )索引越界

访问了不存在的索引,抛出 ArrayIndexOutOfBoundsException

int[] arr = new int[3]; // 索引0~2
System.out.println(arr[3]); // 越界

避免方法:访问索引前确保 0 <= 索引 < 数组长度,通常用arr.length控制循环。

2 )空指针异常

数组变量不再指向任何堆内存空间(记录null),仍试图访问元素,抛出NullPointerException

int[] arr = new int[3];
arr = null;
System.out.println(arr[0]); // 空指针异常

null是引用类型的默认值,表示“空”,不指向任何对象

数组遍历

1 ) 遍历:逐一获取数组中的每个元素。常用for循环配合数组名.length

int[] arr = {11, 22, 33, 44, 55};
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

2 ) 改进:一行打印数组元素

需求:将数组元素按格式 [11, 22, 33, 44, 55] 在一行打印。

public static void printArray(int[] arr) {
    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] + ", ");
        }
    }
    // 换行
    System.out.println();
}

数组获取最大值

1 ) 思路:

  1. 假设第一个元素为最大值 max = arr[0]
  2. 遍历剩余元素,如果发现更大的值,则更新max
  3. 遍历结束,max即为最大值
int[] arr = {12, 45, 98, 73, 60};
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
    if (arr[i] > max) {
        max = arr[i];
    }
}
System.out.println("max:" + max);

最小值同理,只需将比较条件改为 arr[i] < min

数组元素求和

需求:键盘录入5个整数,存入数组并求和。典型动态初始化场景。

Scanner sc = new Scanner(System.in);
int sum = 0;
int[] arr = new int[5];
for (int i = 0; i < arr.length; i++) {
    System.out.println("请输入第" + (i + 1) + "个整数:");
    arr[i] = sc.nextInt();
}
for (int i = 0; i < arr.length; i++) {
    sum += arr[i];
}
System.out.println("sum:" + sum);

数组基本查找

需求:已知数组,键盘录入一个数据,查找其在数组中的索引,找不到返回-1。

int[] arr = {19, 28, 37, 46, 50};
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要查找的元素:");
int num = sc.nextInt();
int index = -1; // 假设不存在 
for (int i = 0; i < arr.length; i++) {
    if (arr[i] == num) {
        index = i;
        break; // 找到后结束循环
    }
}
System.out.println(index);

评委打分案例

需求:6个评委打分(0~100),去掉一个最高分和一个最低分,求平均分(不考虑小数)。

int[] arr = new int[6];
Scanner sc = new Scanner(System.in);
// 录入评委分数,并保证数据合法
for (int i = 0; i < arr.length; i++) {
    System.out.println("请输入第" + (i + 1) + "个评委的打分:");
    int score = sc.nextInt();
    if (score >= 0 && score <= 100) {
        arr[i] = score;
    } else {
        System.out.println("您的打分输入有误, 请检查是否是0-100之间的");
        i--; // 重新输入本位置
    }
}
// 求最大值
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
    if (arr[i] > max) max = arr[i];
}
// 求最小值
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
    if (arr[i] < min) min = arr[i];
}
// 求和
int sum = 0;
for (int i = 0; i < arr.length; i++) {
    sum += arr[i];
}
// 计算平均分
int avg = (sum - max - min) / 4;
System.out.println(avg);

i--的作用:当输入非法分数时,强迫用户重新输入当前评委的分数,保证数组最终只存储合法值。

总结

本文从数组的概念、定义、初始化到内存模型、常见操作和经典案例,全面介绍了Java数组的基础知识。

掌握数组是学习Java集合等高级特性的重要前提,建议多动手练习,理解内存分配与引用机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值