Java 数组详解

数组是 Java 中最基础的数据结构之一,用于存储相同类型的多个元素,具有固定长度、连续内存分配的特点,是处理批量数据的核心工具。本文将从数组的定义、初始化、访问、遍历、常用操作到进阶应用,结合实战代码全面解析 Java 数组的使用,帮你夯实基础、灵活运用。

一、数组核心概念

1. 定义

数组是一种引用数据类型,它将多个相同类型的元素按顺序存储在连续的内存空间中,通过 "数组名 + 索引" 快速访问元素。

2. 核心特性

  • 固定长度:数组一旦创建,长度不可修改(长度由初始化时指定);
  • 相同类型:所有元素必须是同一数据类型(如 int、String、自定义类);
  • 索引访问 :索引从0开始,最大索引为数组长度-1(超出索引会抛ArrayIndexOutOfBoundsException);
  • 内存特性:数组对象存储在堆内存,数组名(引用)存储在栈内存。

3. 数组的分类

  • 按维度:一维数组(常用)、二维数组(矩阵结构)、多维数组(极少用);
  • 按元素类型:基本类型数组(int []、double [])、引用类型数组(String []、Object [])。

二、一维数组的使用(重点)

1. 数组的声明

声明数组有两种语法格式(推荐第一种,更清晰):

java 复制代码
// 格式1(推荐):数据类型[] 数组名;
int[] scores; // 声明一个int类型的数组,变量名为scores
String[] names; // 声明一个String类型的数组

// 格式2:数据类型 数组名[];(兼容C/C++语法,不推荐)
int ages[];

注意 :声明时仅定义数组引用,未分配内存,数组名此时为null

2. 数组的初始化

数组必须初始化后才能使用,初始化的核心是分配内存空间赋值(默认值或自定义值)。分为三种方式:

(1)静态初始化(已知元素值)

直接指定每个元素的值,数组长度由元素个数自动推导:

java 复制代码
// 语法:数据类型[] 数组名 = {元素1, 元素2, ..., 元素n};
int[] scores = {90, 85, 95, 78, 88}; // 长度为5的int数组
String[] names = {"张三", "李四", "王五"}; // 长度为3的String数组

// 完整写法(显式指定new关键字,适合声明和赋值分离场景)
int[] ages = new int[]{20, 21, 22};

注意 :静态初始化不能同时指定长度和元素值(如int[] arr = new int[3]{1,2,3}会编译报错)。

(2)动态初始化(已知长度,未知元素值)

指定数组长度,系统自动为元素分配默认值,后续可手动修改:

java 复制代码
// 语法:数据类型[] 数组名 = new 数据类型[数组长度];
int[] nums = new int[5]; // 长度为5的int数组,默认值为0
double[] prices = new double[3]; // 长度为3的double数组,默认值为0.0
boolean[] flags = new boolean[4]; // 长度为4的boolean数组,默认值为false
String[] address = new String[2]; // 长度为2的String数组,默认值为null

基本类型默认值表

数据类型 默认值
byte/short/int/long 0
float/double 0.0
boolean false
char '\u0000'(空字符)
引用类型(String/Object 等) null

(3)默认初始化(仅声明 + 分配内存)

仅声明数组并分配内存,元素使用系统默认值(同动态初始化):

java 复制代码
int[] arr = new int[4];
System.out.println(arr[0]); // 输出:0(int默认值)

3. 数组的访问与修改

通过 "数组名 [索引]" 访问或修改元素,索引范围是0 ~ 数组长度-1

java 复制代码
public class ArrayAccess {
    public static void main(String[] args) {
        int[] scores = {90, 85, 95, 78};
        
        // 访问元素(索引0对应第一个元素)
        System.out.println("第一个元素:" + scores[0]); // 输出:90
        System.out.println("最后一个元素:" + scores[scores.length - 1]); // 输出:78(length属性获取长度)
        
        // 修改元素
        scores[2] = 100; // 将索引2的元素(原95)改为100
        System.out.println("修改后第三个元素:" + scores[2]); // 输出:100
        
        // 错误示例:索引越界(编译通过,运行时抛异常)
        // System.out.println(scores[4]); // 报错:ArrayIndexOutOfBoundsException
    }
}

关键数组名.length获取数组长度(只读属性,不能修改)。

4. 数组的遍历(核心操作)

遍历是指依次访问数组的每个元素,常用两种方式:for循环(适合需要索引的场景)和for-each循环(适合仅遍历元素的场景)。

(1)普通 for 循环(带索引)

java 复制代码
public class ArrayForLoop {
    public static void main(String[] args) {
        String[] fruits = {"苹果", "香蕉", "橙子", "葡萄"};
        
        // 普通for循环:通过索引遍历
        for (int i = 0; i < fruits.length; i++) {
            System.out.println("索引" + i + ":" + fruits[i]);
        }
    }
}

输出结果

plaintext

索引0:苹果

索引1:香蕉

索引2:橙子

索引3:葡萄

(2)for-each 循环(增强 for 循环,无索引)

语法简洁,无需关注索引,仅遍历元素值(无法修改元素本身,适合读取):

java 复制代码
public class ArrayForEach {
    public static void main(String[] args) {
        int[] nums = {10, 20, 30, 40};
        
        // for-each循环:for (元素类型 变量名 : 数组名)
        for (int num : nums) {
            System.out.println("元素值:" + num);
        }
    }
}

输出结果

plaintext

元素值:10

元素值:20

元素值:30

元素值:40

(3)Java 8+ Stream 遍历(进阶)

结合 Stream API 实现更灵活的遍历(如过滤、排序):

java 复制代码
import java.util.Arrays;

public class ArrayStream {
    public static void main(String[] args) {
        int[] scores = {85, 92, 78, 95, 88};
        
        // Stream遍历:过滤出大于90的分数并打印
        Arrays.stream(scores)
              .filter(score -> score > 90)
              .forEach(score -> System.out.println("高分:" + score));
    }
}

输出结果

plaintext

高分:92

高分:95

三、二维数组(矩阵结构)

二维数组本质是 "数组的数组",即每个元素都是一个一维数组,适用于存储表格、矩阵等结构化数据。

1. 声明与初始化

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

java 复制代码
// 格式1:数据类型[][] 数组名 = {{元素1,元素2}, {元素3,元素4}, ...};
int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; // 3行3列的矩阵

// 格式2:显式指定new关键字
String[][] students = new String[][]{{"张三", "男"}, {"李四", "女"}};

(2)动态初始化(已知行数和列数)

java 复制代码
// 格式1:指定行数和列数(每行列数相同,规则矩阵)
int[][] arr1 = new int[2][3]; // 2行3列,元素默认值为0

// 格式2:仅指定行数,列数动态分配(每行列数可不同,不规则矩阵)
int[][] arr2 = new int[3][]; // 3行,列数未指定
arr2[0] = new int[2]; // 第1行2列
arr2[1] = new int[4]; // 第2行4列
arr2[2] = new int[3]; // 第3行3列

2. 访问与遍历

通过 "数组名 [行索引][列索引]" 访问元素,遍历需嵌套循环:

java 复制代码
public class TwoDimensionalArray {
    public static void main(String[] args) {
        int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        
        // 访问元素(第2行第3列,索引从0开始)
        System.out.println("matrix[1][2]:" + matrix[1][2]); // 输出:6
        
        // 遍历二维数组(嵌套for循环)
        System.out.println("二维数组遍历:");
        for (int i = 0; i < matrix.length; i++) { // 遍历行(matrix.length是行数)
            for (int j = 0; j < matrix[i].length; j++) { // 遍历列(matrix[i].length是第i行的列数)
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println(); // 换行
        }
        
        // for-each遍历二维数组
        System.out.println("for-each遍历:");
        for (int[] row : matrix) { // 每行是一个int[]数组
            for (int num : row) { // 遍历每行的元素
                System.out.print(num + " ");
            }
            System.out.println();
        }
    }
}

输出结果

plaintext

css 复制代码
matrix[1][2]:6
二维数组遍历:
1 2 3 
4 5 6 
7 8 9 
for-each遍历:
1 2 3 
4 5 6 
7 8 9 
相关推荐
CoderYanger1 小时前
递归、搜索与回溯-综合练习:28.不同路径Ⅲ
java·算法·leetcode·深度优先·1024程序员节
用户84913717547161 小时前
Tomcat 为什么要“造反”?深度解析 Java 类加载机制的“守”与“破”
java·jvm
jiayong231 小时前
Elasticsearch Java 开发完全指南
java·大数据·elasticsearch
321茄子1 小时前
MySQL 事务隔离性及锁
java·数据库·mysql
杀死那个蝈坦1 小时前
UV 统计(独立访客统计)
java·jvm·spring·kafka·tomcat·maven
带刺的坐椅1 小时前
Solon AI 开发学习7 - chat - 四种消息类型及提示语增强
java·ai·llm·solon
济宁雪人1 小时前
Java安全基础——序列化/反序列化
java·开发语言
1***Q7841 小时前
后端在微服务中的服务路由
java·数据库·微服务
q***01771 小时前
Java进阶--IO流
java·开发语言