一、今日学习目标

  1. 理解数组的概念与特点,掌握同类型数据的隐式转换规则
  2. 完整掌握数组的定义方式初始化方式,明确二者的区别与联系
  3. 掌握数组静态初始化的两种写法、动态初始化的格式,明确使用场景与注意事项
  4. 理解数组地址值的含义,能解析地址值的组成部分
  5. 掌握数组元素的访问、遍历方法,区分下标变量i与数组元素arr[i]
  6. 了解数组常见异常(索引越界、空指针)的产生原因与规避方法
  7. 通过 7 个实战练习,掌握数组的遍历、求和、计数、最值查找、修改、交换、打乱等核心操作

二、核心知识点

(一)数组的概念

  1. 定义:数组是 Java 中用于存储相同数据类型多个元素的容器,元素按顺序排列,每个元素通过下标(索引)访问。
  2. 核心特点
    • 长度固定:数组一旦初始化,长度不可改变
    • 类型统一:所有元素必须是同一数据类型,支持自动隐式转换(如byte/short/char类型存入int数组时会自动提升)
    • 下标从 0 开始:数组的第一个元素下标为 0,最后一个元素下标为数组名.length - 1
  3. 隐式转换说明:数组要求元素类型统一,小范围类型可以自动转换为大范围类型(如byte→int),但大范围类型不能直接存入小范围类型数组。

(二)数组的定义(声明)方式

数组定义仅声明数组变量,不分配内存空间,Java 有且仅有两种标准定义格式,仅写法不同,效果完全一致:

格式类型 写法 示例 说明
推荐写法(Java 标准) 数据类型[] 数组名; String[] students; []紧跟数据类型,明确表示这是该类型的数组,语义清晰,是行业主流写法
兼容写法(C 语言遗留) 数据类型 数组名[]; String teachers[]; []紧跟变量名,是为了兼容 C 语言习惯保留的写法,可读性差,不推荐

(三)数组的初始化

初始化是为定义好的数组分配内存空间,并赋值的过程,必须初始化后才能使用数组,分为静态初始化动态初始化两大类,其中静态初始化又分为两种写法。

1. 静态初始化(初始化时已知所有元素值)

静态初始化的核心是:手动指定元素值,由系统自动计算数组长度,分为两种写法:

写法 格式 示例 特点
简化写法(最常用) 数据类型[] 数组名 = {元素1,元素2,...}; String[] students = {"李明","张伟","王旗"}; 省略new 数据类型[],代码简洁,必须和定义写在同一行
完整写法 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,...}; String[] teachers = new String[]{"孙强","赵立","周国"}; 完整指定new和类型,可读性强,可拆分为 “定义 + 赋值” 两步
2. 动态初始化(初始化时仅知道数组长度)
  • 格式:数据类型[] 数组名 = new 数据类型[长度];
  • 示例:int[] arr = new int[5];
  • 特点:手动指定数组长度,系统自动为元素赋予默认值(int=0double=0.0boolean=false引用类型=null
3. 核心注意事项
  • 静态、动态初始化不能混用new int[3]{1,2,3} 语法错误
  • 数组一旦初始化,长度永久固定,无法修改
  • 简化版静态初始化必须和定义写在同一行,不能拆分(如String[] students; students = {"李明","张伟"}; 是错误的)


(四)数组的地址值

  1. 含义:数组是引用数据类型,变量名存储的不是元素本身,而是数组在堆内存的地址值
  2. 地址值格式解析[Ljava.lang.String;@15db9742
    • [ :代表这是一个数组
    • L :代表元素是引用类型
    • java.lang.String :数组元素的具体类型
    • @ :固定分隔符
    • 15db9742 :十六进制内存地址

(五)数组元素的访问

  1. 获取元素值格式:数组名[索引];示例:arr[0] 获取数组第一个元素。

  2. 修改 / 存入数据格式:数组名[索引] = 数值;示例:arr[0] = 10; 给第一个元素赋值。

  3. 关键注意事项

    • 合法索引范围:0 ≤ 索引 ≤ 数组长度-1
    • i 是索引(数字),arr[i] 是索引对应的元素,二者完全不同。

(六)数组的遍历

遍历:依次访问数组中每一个元素。

  1. 普通 for 循环(最通用)
for(int i=0; i<数组名.length; i++){
    System.out.println(数组名[i]);
}
  • 数组名.length:获取数组长度,避免写死数字导致索引越界。
  1. 增强 for 循环(仅读取元素)
for(数据类型 变量名 : 数组名){
    System.out.println(变量名);
}

(七)数组的常见问题

  1. 索引越界异常(ArrayIndexOutOfBoundsException)

    • 原因:访问了超出0 ~ length-1范围的索引
    • 避免:使用数组名.length控制循环条件。
  2. 空指针异常(NullPointerException)

    • 原因:数组变量为null,却访问元素或长度
    • 避免:确保数组已完成初始化再使用。

三、实战练习解析

练习 1:数组的定义与基础遍历

题目:定义两个字符串数组,分别存储学生和老师的名字,并遍历打印所有元素。

解析:通过数组名.length获取数组长度,避免了索引越界问题,成功遍历两个数组的所有元素。


练习 2:数组元素求和

题目:定义一个整数数组,遍历数组并计算所有元素的和。

解析:定义变量sum初始化为 0,遍历数组时将每个元素累加到sum中,最终得到数组元素的总和。


练习 3:统计数组中的偶数个数

题目:定义一个整数数组,遍历数组并统计其中偶数的个数,同时打印所有偶数。

解析:通过numbers[i] % 2 == 0判断元素是否为偶数,符合条件时打印元素并将计数器count加 1,最终得到偶数的个数。


练习 4:根据奇偶性修改数组元素

题目:定义一个整数数组,遍历数组,将偶数除以 2,奇数乘以 2,并打印修改后的数组。

解析:遍历数组时,通过if-else判断元素的奇偶性,对数组元素进行修改,再遍历打印修改后的结果。


练习 5:查找数组中的最大值和最小值

题目:定义一个整数数组,遍历数组并找出其中的最大值和最小值。

解析:先将数组的第一个元素作为初始的最大值 / 最小值,遍历数组时与每个元素比较,更新最大值 / 最小值。


练习 6:计算随机数组的平均值并统计大于平均值的元素

题目:动态初始化一个长度为 5 的整数数组,生成 1-50 的随机数填充数组,计算平均值并统计大于平均值的元素。

解析:使用Random类生成随机数填充动态初始化的数组,计算数组元素的平均值,再遍历数组筛选出大于平均值的元素。


练习 7:数组元素的交换与反转、打乱

(1)指定下标元素交换

题目:定义一个数组,交换下标 1 和下标 3 的元素。代码

解析:使用临时变量temp作为中间容器,完成两个元素的交换。

(2)数组反转

题目:定义一个数组,实现数组元素的反转(首尾交换)。

解析:使用双指针i(从前往后)和j(从后往前),交换对应位置的元素,直到i >= j

(3)数组元素打乱

题目:定义一个数组,使用随机数实现数组元素的打乱。

解析:遍历数组时,生成一个随机下标,将当前元素与随机下标对应的元素交换,实现数组的打乱效果。


四、今日学习总结

  1. 数组定义:只有两种格式,数据类型[] 数组名 是行业标准推荐写法。
  2. 数组初始化:分为静态初始化(两种写法,已知元素)和动态初始化(指定长度,未知元素),初始化后长度不可变。
  3. 核心规则:索引从 0 开始,合法范围0 ~ length-1,遍历优先用数组名.length控制循环条件。
  4. 高频操作:遍历、求和、统计、最值、修改、交换、反转、打乱,全部基于索引访问。
  5. 常见异常:索引越界、空指针,严格遵守规则可完全避免。
  6. 引用类型特点:数组变量存储的是内存地址值,元素实际存储在堆内存中。

更多推荐