Java基础入门:数组详解

前言:掌握了Java变量、运算符和流程控制语句后,我们会遇到一个新问题——如何高效存储多个同类型的数据?比如存储一个班级50名学生的成绩、10个商品的价格,此时单独定义多个变量会非常繁琐。而「数组」就是Java中专门用来存储多个同类型数据的基础容器,简单、高效、易操作。这篇文章全程避开复杂术语,用「生活化类比+可直接运行的代码案例」,把Java数组的定义、初始化、遍历、常用操作和新手避坑点讲透,每个案例都带详细注释,新手跟着敲一遍就能掌握,复制粘贴就能在CSDN发布,助力你稳步夯实Java基础,衔接后续学习!

温馨提示:所有代码均适配JDK8及以上版本,可直接复制到IDEA、Eclipse等Java编辑器运行,报错可评论区留言,逐一解答;建议结合前三篇(变量、运算符、流程控制)一起学习,衔接更顺畅,理解更轻松~

一、先搞懂:什么是Java数组?

1. 通俗理解

数组就像「一个带格子的收纳盒」—— 收纳盒有固定的格子数量,每个格子只能放同一种类型的物品(比如全部放苹果、全部放书本),每个格子都有自己的编号(从0开始),我们通过编号就能快速找到对应格子里的物品。

类比到Java中:数组是「存储多个同类型数据的容器」,有固定的长度(一旦创建,长度不能修改),每个数据称为「元素」,每个元素都有对应的「索引」(编号,从0开始),通过索引就能快速访问、修改元素。

比如:用一个数组存储3名学生的成绩(90、85、95),数组长度是3,索引分别是0、1、2,通过索引0就能找到90,索引1找到85,非常便捷。

2. 数组的核心特点

    1. 同类型:数组中所有元素的数据类型必须一致(比如不能同时存储int整数和String字符串);
    1. 固定长度:数组一旦创建,长度就固定不变(比如创建长度为5的数组,只能存储5个元素,不能多也不能少);
    1. 索引从0开始:第一个元素索引是0,第二个是1,以此类推,最后一个元素索引是「数组长度-1」(新手最容易踩坑的点);
    1. 存储在连续内存中:访问速度快,通过索引能直接定位到元素。

二、数组的定义与初始化(核心步骤,必掌握)

使用数组分为两步:先定义数组(声明数组),再初始化数组(给数组赋值,确定长度)。新手重点掌握两种初始化方式,按需选择即可。

1. 数组的定义(2种写法,都常用)

定义数组的核心是「指定数据类型」和「数组名称」,告诉编译器“这是一个存储某种类型数据的数组”。

两种写法(效果完全一致,新手任选一种,建议固定一种):

  • 写法1:数据类型[] 数组名; (推荐,更规范,一眼能看出是数组)

  • 写法2:数据类型 数组名[]; (兼容C语言写法,不推荐新手使用)

// 数组定义案例(两种写法)
public class ArrayDefine {
    public static void main(String[] args) {
        // 写法1:推荐,数据类型[] 数组名
        int[] scores; // 定义一个存储int类型(成绩)的数组,数组名scores
        String[] names; // 定义一个存储String类型(姓名)的数组,数组名names
        
        // 写法2:不推荐,数据类型 数组名[]
        int ages[]; // 效果和int[] ages一致,但可读性差
    }
}

注意:只定义数组,没有初始化,数组是「空的」(不能直接使用,否则报错),必须初始化后才能使用。

2. 数组的初始化(2种方式,必掌握)

初始化的核心:给数组分配内存空间、确定数组长度、给元素赋值。分为「静态初始化」和「动态初始化」,新手根据场景选择。

(1)静态初始化(已知所有元素值,推荐)

适用场景:提前知道数组中所有元素的值(比如存储固定的3名学生成绩、5个固定数字),不需要手动指定数组长度(编译器会自动根据元素个数计算长度)。

语法:
// 写法1:定义+初始化一步完成(推荐)
数据类型[] 数组名 = {元素1, 元素2, 元素3, …};

// 写法2:完整写法(了解即可)
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元素3, …};

// 静态初始化案例(最常用)
public class ArrayStaticInit {
    public static void main(String[] args) {
        // 案例1:存储3名学生的成绩(int类型)
        int[] scores = {90, 85, 95}; // 编译器自动计算长度为3,索引0=90,1=85,2=95
        
        // 案例2:存储4个姓名(String类型)
        String[] names = {"张三", "李四", "王五", "赵六"}; // 长度为4,索引0-3
        
        // 案例3:完整写法(了解)
        double[] heights = new double[]{1.75, 1.80, 1.68};
        
        // 打印数组(后续讲遍历,这里先简单查看)
        System.out.println("成绩数组:" + scores); // 输出数组地址(不是元素,后续详解)
        System.out.println("第一个成绩:" + scores[0]); // 通过索引访问,输出:90
    }
}
(2)动态初始化(未知元素值,知道长度)

适用场景:不知道数组中具体元素值,但知道数组长度(比如存储一个班级50名学生的成绩,先创建长度为50的数组,后续再赋值)。

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

注意:动态初始化后,数组元素会有「默认值」(不是空,新手必记):

  • 整数型(int、byte等):默认值0;

  • 浮点型(double、float):默认值0.0;

  • 布尔型(boolean):默认值false;

  • 引用类型(String等):默认值null。

// 动态初始化案例
public class ArrayDynamicInit {
    public static void main(String[] args) {
        // 案例1:创建长度为5的int数组(存储5名学生成绩,后续赋值)
        int[] scores = new int[5]; // 长度为5,索引0-4,默认值都是0
        
        // 给数组元素赋值(通过索引赋值)
        scores[0] = 88;
        scores[1] = 92;
        scores[2] = 79;
        scores[3] = 95;
        scores[4] = 85;
        
        // 案例2:创建长度为3的double数组,默认值0.0
        double[] weights = new double[3];
        System.out.println(weights[0]); // 输出:0.0(默认值)
        
        // 案例3:创建长度为2的String数组,默认值null
        String[] names = new String[2];
        System.out.println(names[0]); // 输出:null(默认值)
    }
}

3. 新手避坑重点(初始化常见错误)

  • 避坑1:静态初始化不能同时指定长度和元素,比如int[] scores = new int[3]{90,85,95}(报错),要么指定元素(自动算长度),要么指定长度(动态初始化);

  • 避坑2:数组索引越界(最常见报错):比如长度为3的数组,索引只能是0、1、2,访问scores[3]会报错(索引超出范围);

  • 避坑3:数组长度不能修改,比如创建长度为5的数组后,不能再增加或减少长度;

  • 避坑4:动态初始化后,元素有默认值,不是空,比如int数组默认值0,不是没有值。

// 初始化避坑案例
public class ArrayInitPitfall {
    public static void main(String[] args) {
        // 避坑1:静态初始化不能同时指定长度和元素
        // int[] scores = new int[3]{90,85,95}; // 报错
        
        // 避坑2:索引越界(长度为3,索引0-2)
        int[] scores = {90,85,95};
        // System.out.println(scores[3]); // 报错:ArrayIndexOutOfBoundsException(索引越界)
        
        // 避坑3:数组长度不能修改
        // scores.length = 5; // 报错:不能修改数组长度
    }
}

三、数组的核心操作(遍历、访问、修改,必掌握)

数组的核心操作的是「访问元素」「修改元素」「遍历所有元素」,结合流程控制语句(for循环)使用,是新手必须熟练掌握的技能。

1. 访问数组元素(通过索引)

语法:数组名[索引]; (通过索引就能访问对应位置的元素)

// 访问数组元素案例
public class ArrayAccess {
    public static void main(String[] args) {
        int[] scores = {90, 85, 95, 88, 92};
        
        // 访问单个元素(索引0-4)
        System.out.println("第一个成绩:" + scores[0]); // 输出:90
        System.out.println("第三个成绩:" + scores[2]); // 输出:95
        System.out.println("最后一个成绩:" + scores[4]); // 输出:92
        
        // 访问数组长度(数组名.length,返回数组长度)
        System.out.println("数组长度:" + scores.length); // 输出:5
        // 访问最后一个元素的简化写法(避免索引越界)
        System.out.println("最后一个成绩(简化):" + scores[scores.length - 1]);
    }
}

重点:数组名.length 可以获取数组的长度,访问最后一个元素时,用 scores[scores.length - 1],能有效避免索引越界。

2. 修改数组元素(通过索引赋值)

语法:数组名[索引] = 新值; (通过索引找到元素,替换成新值)

// 修改数组元素案例
public class ArrayModify {
    public static void main(String[] args) {
        int[] scores = {90, 85, 95, 88, 92};
        System.out.println("修改前,第二个成绩:" + scores[1]); // 输出:85
        
        // 修改索引1的元素(85→89)
        scores[1] = 89;
        System.out.println("修改后,第二个成绩:" + scores[1]); // 输出:89
        
        // 批量修改(结合for循环)
        for (int i = 0; i < scores.length; i++) {
            scores[i] += 2; // 所有成绩加2
        }
        System.out.println("所有成绩加2后,最后一个成绩:" + scores[4]); // 输出:94
    }
}

3. 数组遍历(遍历所有元素,高频使用)

遍历:就是「依次访问数组中的每一个元素」,比如打印所有成绩、计算所有元素的和,最常用的方式是「for循环遍历」,新手重点掌握。

(1)普通for循环遍历(最常用,灵活)

利用索引从0开始,循环到数组长度-1,依次访问每个元素,适合需要修改元素、获取索引的场景。

// 普通for循环遍历案例
public class ArrayForEach1 {
    public static void main(String[] args) {
        int[] scores = {90, 85, 95, 88, 92};
        
        // 遍历数组:索引从0到scores.length-1
        System.out.println("数组中的所有成绩:");
        for (int i = 0; i < scores.length; i++) {
            System.out.println("索引" + i + ":" + scores[i]);
        }
        
        // 遍历数组,计算所有成绩的和
        int sum = 0;
        for (int i = 0; i < scores.length; i++) {
            sum += scores[i];
        }
        System.out.println("所有成绩的和:" + sum); // 输出:450
    }
}
(2)增强for循环遍历(for-each,简化写法)

语法:for (数据类型 变量名 : 数组名) { 循环体; }

适用场景:只需访问元素,不需要修改元素、不需要获取索引(简化代码,可读性强),新手可以灵活使用。

// 增强for循环遍历案例
public class ArrayForEach2 {
    public static void main(String[] args) {
        String[] names = {"张三", "李四", "王五", "赵六"};
        
        // 增强for循环:依次取出数组中的每个元素,赋值给name变量
        System.out.println("数组中的所有姓名:");
        for (String name : names) {
            System.out.println(name); // 直接打印元素,无需索引
        }
        
        // 增强for循环计算成绩和
        int[] scores = {90, 85, 95, 88, 92};
        int sum = 0;
        for (int score : scores) {
            sum += score;
        }
        System.out.println("成绩和:" + sum); // 输出:450
    }
}

新手避坑:增强for循环中,变量(比如name、score)是数组元素的“副本”,修改变量不会改变数组中的原始元素(比如score = 100,数组中的元素不会变)。

四、数组的常见应用场景

结合前面的知识点,整理3个新手高频应用场景,代码可直接复制运行,套用即可解决实际问题。

场景1:计算数组中所有元素的平均值

// 计算数组平均值
public class ArrayAverage {
    public static void main(String[] args) {
        // 存储5名学生成绩
        int[] scores = {88, 92, 79, 95, 85};
        int sum = 0;
        
        // 遍历数组,计算总和
        for (int score : scores) {
            sum += score;
        }
        
        // 计算平均值(注意:整数除法取整,需转成double)
        double average = (double) sum / scores.length;
        System.out.println("5名学生的平均成绩:" + average); // 输出:87.8
    }
}

场景2:查找数组中的最大值(最小值同理)

// 查找数组最大值
public class ArrayMax {
    public static void main(String[] args) {
        int[] scores = {88, 92, 79, 95, 85};
        int max = scores[0]; // 假设第一个元素是最大值
        
        // 遍历数组,对比每个元素,更新最大值
        for (int i = 1; i < scores.length; i++) {
            if (scores[i] > max) {
                max = scores[i]; // 找到更大的元素,更新max
            }
        }
        
        System.out.println("数组中的最大值:" + max); // 输出:95
    }
}

场景3:数组元素反转(比如[1,2,3]→[3,2,1])

// 数组元素反转
public class ArrayReverse {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        System.out.println("反转前:");
        for (int num : arr) {
            System.out.print(num + " "); // 输出:1 2 3 4 5
        }
        
        // 反转逻辑:首尾元素交换,依次向中间靠拢
        for (int i = 0; i < arr.length / 2; i++) {
            // 临时变量存储首元素
            int temp = arr[i];
            // 首尾元素交换
            arr[i] = arr[arr.length - 1 - i];
            arr[arr.length - 1 - i] = temp;
        }
        
        System.out.println("\n反转后:");
        for (int num : arr) {
            System.out.print(num + " "); // 输出:5 4 3 2 1
        }
    }
}

五、新手常见报错汇总(避坑天花板)

整理了新手使用数组时,最常遇到的4种报错,附上原因和解决方案,看完少踩90%的坑!

  • 报错1:ArrayIndexOutOfBoundsException(数组索引越界)
    原因:访问的索引超出数组范围(比如长度为3的数组,访问索引3);
    解决方案:检查索引是否在0~数组长度-1之间,用scores.length-1获取最后一个元素的索引。

  • 报错2:NullPointerException(空指针异常)
    原因:只定义了数组,没有初始化(比如int[] scores; 就直接访问scores[0]);
    解决方案:先对数组进行静态或动态初始化,再访问元素。

  • 报错3:illegal initializer for int[](int数组的非法初始化)
    原因:静态初始化同时指定长度和元素(比如int[] scores = new int[3]{90,85,95});
    解决方案:静态初始化只写元素(不指定长度),或动态初始化只指定长度(不写元素)。

  • 报错4:incompatible types(类型不兼容)
    原因:数组中存储了不同类型的元素(比如int[] scores = {90, “85”, 95});
    解决方案:确保数组中所有元素的数据类型一致,和数组定义的类型匹配。

六、总结

Java数组的核心,新手只需掌握以下4点,就能轻松应对入门场景:

    1. 数组是存储多个同类型数据的容器,有固定长度,索引从0开始;
    1. 数组使用步骤:定义→初始化(静态/动态)→ 访问/修改/遍历;
    1. 遍历数组:普通for循环(灵活,可获取索引)、增强for循环(简化,适合仅访问元素);
    1. 重点避坑:索引不越界、初始化后再使用、数组长度不可修改。

练习建议:结合前三篇的知识点,自己写代码练习——定义数组、初始化数组、遍历数组、计算平均值、查找最大值,多敲多练,就能熟练掌握。数组是Java中最基础的容器,后续学习集合、字符串等内容,都离不开数组的基础逻辑。

如果有报错、有疑问,欢迎在评论区留言,逐一解答!觉得有用的话,点赞收藏不迷路,关注我,后续持续更新Java新手基础教程,陪你从零学会Java~

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐