一、数组的定义与内存模型

1. 数组的三种定义方式

// 1. 静态初始化(定义时直接赋值)
int[] array1 = {1,2,3,4};
// 2. 动态初始化(指定长度,默认值填充)
int[] array2 = new int[10];
// 3. 动态初始化(指定初始值)
int[] array3 = new int[]{1,2,3,4,5,6,7};
  1. 内存核心概念
    基本数据类型:变量直接存储值(如 int 默认 0 , char 默认 \u0000 , double 默认 0.0 , boolean 默认 false )。
    引用数据类型:变量存储的是对象的内存地址(数组、类、接口等都属于引用类型)。
    Java虚拟机运行时的数据区
    虚拟机栈:存储局部变量(如 array 引用变量)。
    堆:存储真正的数组对象(数据存在堆上)。
    方法区:存储类信息、常量等。
    在这里插入图片描述
int[] array = {1,2,3,4};
int[] array2 = array; // 两个引用指向同一个堆上的数组对象
array[0] = 99;
System.out.println(array2[0]); // 输出99,因为共享同一块内存

这里的array和array2指向堆中同一个对象

二、数组的核心操作

1. 遍历与打印

普通for循环:可以获取下标,适合需要操作索引的场景。
增强for循环(for-each):只能遍历元素,拿不到下标,适合单纯遍历。

for(int x:array){
		System.out.println(x+" ");
}

工具类打印: Arrays.toString() 快速打印一维数组, Arrays.deepToString() 打印二维数组。

方法分类 方法名 方法用途 注意点
排序 sort() 对一维数组进行升序排序 对象数组需实现Comparable接口(后续文章中会讲到)
查找 binarySearch() 在已排序的数组中查找指定元素,返回索引(未找到返回-(插入点)-1 必须先排序
填充 fill() 将数组全部 / 指定范围元素填充为指定值
比较 equals() 比较两个一维数组的长度 + 对应位置元素是否完全相同 仅适用于一维数组,多维数组需用deepEquals()
deepEquals() 比较多维数组的内容是否完全相同
字符串转换 toString() 将一维数组转为[元素1, 元素2, …]格式的易读字符串 多维数组需用deepToString(),否则输出数组内存地址
deepToString() 将多维数组转为易读的字符串形式
数组复制 copyIOf() 复制数组前 N 个元素(N > 原长度时补默认值:int 补 0,对象补 null)
copyOfRange() 复制数组指定范围 范围超出原数组长度时,补对应类型默认值
各个方法名的用法示例
sort()方法
 // 1. 基本类型数组排序(int数组)
 int[] intArr = {3, 1, 4, 2};
Arrays.sort(intArr);
 System.out.println("排序后int数组:" + Arrays.toString(intArr)); // 输出 [1, 2, 3, 4]
// 2. 局部排序
int[] partialArr = {5, 2, 9, 1, 7};
Arrays.sort(partialArr, 1, 4); // 排序索引1-3的元素,java中前闭后开
 System.out.println("局部排序后:" + Arrays.toString(partialArr)); // 输出 [5, 1, 2, 9, 7]
binarySearch()方法
int[] arr = {1, 2, 3, 4, 5};
        // 查找存在的元素
        int index1 = Arrays.binarySearch(arr, 3);
        System.out.println("元素3的索引:" + index1); // 输出 2
        // 查找不存在的元素
        int index2 = Arrays.binarySearch(arr, 6);
        System.out.println("元素6的查找结果:" + index2); // 输出 -6(插入点是5,-(5)-1=-6)

看插入点的方法:1.遍历已排序数组,找到第一个大于目标值的元素的索引,这个索引就是插入点;
2.如果目标值大于所有元素,插入点 = 数组长度(如上例中 10 的插入点是 5,数组长度正好是 5);
3.如果目标值小于所有元素,插入点 = 0。

fill()
// 1. 填充所有元素
int[] arr1 = new int[5];
Arrays.fill(arr1, 8);
System.out.println("填充所有元素:" + Arrays.toString(arr1)); // 输出 [8, 8, 8, 8, 8]
// 2. 填充指定范围元素
int[] arr2 = new int[5];
Arrays.fill(arr2, 1, 4, 9); // 填充索引1-3的元素为9
System.out.println("填充指定范围:" + Arrays.toString(arr2)); // 输出 [0, 9, 9, 9, 0]
数组比较:equals () 和 deepEquals ()
// 1. 一维数组比较
        int[] arr1 = {1, 2, 3};
        int[] arr2 = {1, 2, 3};
        int[] arr3 = {1, 3, 2};
        System.out.println("arr1和arr2是否相等:" + Arrays.equals(arr1, arr2)); // 输出 true
        System.out.println("arr1和arr3是否相等:" + Arrays.equals(arr1, arr3)); // 输出 false

        // 2. 多维数组比较(必须用deepEquals)
        int[][] multiArr1 = {{1,2}, {3,4}};
        int[][] multiArr2 = {{1,2}, {3,4}};
        System.out.println("多维数组比较(equals):" + Arrays.equals(multiArr1, multiArr2)); // 输出 false(比较的是数组引用)
        System.out.println("多维数组比较(deepEquals):" + Arrays.deepEquals(multiArr1, multiArr2)); // 输出 true
数组转字符串:toString () 和 deepToString ()
// 1. 一维数组转字符串
        int[] arr = {1, 2, 3};
        System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3]

        // 2. 多维数组转字符串
        int[][] multiArr = {{1,2}, {3,4}};
        System.out.println(Arrays.deepToString(multiArr)); // 输出 [[1, 2], [3, 4]]
数组复制:copyOf () 和 copyOfRange ()
int[] original = {1, 2, 3, 4, 5};
        // 1. 复制前3个元素
        int[] copy1 = Arrays.copyOf(original, 3);
        System.out.println("copyOf前3个:" + Arrays.toString(copy1)); // 输出 [1, 2, 3]
        // 2. 复制超出原长度(补0)
        int[] copy2 = Arrays.copyOf(original, 7);
        System.out.println("copyOf超出长度:" + Arrays.toString(copy2)); // 输出 [1, 2, 3, 4, 5, 0, 0]
        // 3. 复制指定范围(索引1到4)
        int[] copy3 = Arrays.copyOfRange(original, 1, 4);
        System.out.println("copyOfRange:" + Arrays.toString(copy3)); // 输出 [2, 3, 4]
打印数组的各个方法
int[] array = {1,2,3,4,5};
// 普通for循环
for (int i = 0; i < array.length; i++) {
    System.out.print(array[i] + " ");
}
// for-each循环
for (int x : array) {
    System.out.print(x + " ");
}
// 工具类打印
System.out.println(Arrays.toString(array)); // 输出[1, 2, 3, 4, 5]

2.自定义二分查找:

public static int binarySearch(int[] array, int key) {
   int left = 0;
   int right = array.length - 1;
   while (left <= right) {
       int mid = (left + right) / 2;
       if (array[mid] < key) {
           left = mid + 1;
       } else if (array[mid] > key) {
           right = mid - 1;
       } else {
           return mid; // 找到目标
       }
   }
   return -1; // 未找到
}

三、数组常见异常

  1. 数组越界异常: ArrayIndexOutOfBoundsException
    原因:访问了数组不存在的下标(如 array[-1] 或 array[array.length] )。
  2. 空指针异常: NullPointerException
    原因:引用变量为 null 时,尝试访问其指向的对象(如 int[] arr = null; arr[0] = 1; )。
  3. 算术异常: ArithmeticException
    原因:数学运算错误(如除零操作)。

四、二维数组与特殊算法

1. 二维数组定义

定义示例

// 静态初始化
int[][] array1 = {{1,2,3}, {4,5,6}};
// 动态初始化
int[][] array2 = new int[2][3];
// 不规则二维数组
int[][] array3 = new int[2][];
array3[0] = new int[]{1,2,3};
array3[1] = new int[]{4,5,6,7,8,9};

2. 经典算法题:只出现一次的数字

利用异或运算(相同为0,不同为1)的性质:
任何数和0异或等于它本身: a ^ 0 = a
任何数和自身异或等于0: a ^ a = 0
异或满足交换律和结合律

// 数组中只有一个数字出现一次,其余都出现两次
public static int findSingleNumber(int[] array) {
    int ret = array[0];
    for (int i = 1; i < array.length; i++) {
        ret ^= array[i];
    }
    return ret;
}

五、总结与学习建议

  1. 数组核心:理解引用类型的内存模型,掌握遍历、拷贝、排序、查找等基础操作。
  2. 异常处理:重点关注数组越界和空指针异常,养成良好的编码习惯。
  3. 实践优先:多写代码练习,比如实现冒泡排序、二分查找、二维数组遍历等。
    后续继续学习:构造方法、封装、继承、多态等面向对象核心特性.
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐