讲解

数组是长度固定的同类型数据容器:声明 int[] scores 就规定了这个数组只能装 int,创建时长度就定死,之后不能变长也不能变短。创建有两种方式:new int[5] 造一个长度为 5、全部元素为默认值(int 是 0)的数组;int[] arr = {90, 85, 77} 直接在创建时赋好初值。访问用下标,从 0 开始,最后一个元素的下标是 length - 1;length 是数组的属性(不带括号,别和字符串的 length() 方法记混)。

数组一旦越界(访问 arr[-1] 或 arr[length]),运行时立刻抛 ArrayIndexOutOfBoundsException,程序中止。这个异常是新手期见的最多的错误之一,防它的办法就是牢记「下标从 0 到 length-1」,遍历优先用增强 for。数组的元素如果是基本类型,创建时自动填默认值;如果是引用类型(如 String[]),每个位置默认是 null,调用方法前要先填对象进去,否则空指针异常。

java.util.Arrays 工具类提供了一批静态方法:Arrays.toString(arr) 把数组转成可打印的字符串(直接 System.out.println(arr) 只会打印一串看不懂的地址)、Arrays.sort(arr) 原地升序排序、Arrays.copyOf(arr, 新长度) 复制并改变长度、Arrays.equals(a, b) 按内容比较两个数组(数组的 == 和 equals 都只比地址)。二维数组 int[][] 就是「元素是数组的数组」,用双重循环遍历。

示例

创建、赋值、遍历、打印一个数组:

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] scores = {90, 85, 77, 92, 68};
        System.out.println("人数:" + scores.length);
        System.out.println("第一个分数:" + scores[0]);
        System.out.println("最后一个分数:" + scores[scores.length - 1]);
        System.out.println("全部:" + Arrays.toString(scores));

        int total = 0;
        int max = scores[0];
        for (int s : scores) {
            total += s;
            if (s > max) {
                max = s;
            }
        }
        System.out.println("平均分:" + (double) total / scores.length);
        System.out.println("最高分:" + max);
    }
}

排序、复制、扩容都靠 Arrays 工具类:

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] nums = {5, 2, 8, 1, 9};
        Arrays.sort(nums);
        System.out.println("排序后:" + Arrays.toString(nums));

        int[] bigger = Arrays.copyOf(nums, 8);
        System.out.println("扩容后长度:" + bigger.length + ",内容:" + Arrays.toString(bigger));

        int[] copy = Arrays.copyOf(nums, nums.length);
        System.out.println("内容相等?" + Arrays.equals(nums, copy));
        System.out.println("引用相等?" + (nums == copy));
    }
}

二维数组的创建与双重循环遍历:

public class Main {
    public static void main(String[] args) {
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6},
        };
        System.out.println("行数:" + matrix.length + ",列数:" + matrix[0].length);
        for (int[] row : matrix) {
            for (int cell : row) {
                System.out.print(cell + " ");
            }
            System.out.println();
        }
    }
}

常见坑

  • 下标越界:访问 arr[arr.length] 抛 ArrayIndexOutOfBoundsException。报错信息里的下标值和数组长度是定位问题的关键线索。
  • 直接打印数组:System.out.println(arr) 输出的是 [I@6d06d69c 这样的类型加哈希值,不是内容。打印数组用 Arrays.toString,二维数组用 Arrays.deepToString。
  • 用 == 比较两个数组:数组的 == 和默认 equals 比的都是地址,内容相同也是 false。比较内容用 Arrays.equals。
  • 想给数组动态加元素:数组长度创建后就锁死了,「加元素」意味着新建一个更长的数组再拷贝。需要频繁增删的场合应该用集合章节的 ArrayList。

小结

数组定长、同类型、下标从 0 开始;越界即异常,工具方法找 Arrays。下一节学习把可复用的逻辑封装起来:方法。