Java中的数组是固定长度的数据结构,本身没有提供原生的删除元素方法,开发者需要手动实现删除逻辑,这个过程中很容易因为逻辑设计不当引发各类异常。下面先介绍常见的异常场景和对应的修复方式。

常见异常场景及原因分析
1. 数组索引越界异常
很多开发者在删除元素时,会直接操作原数组的索引,当删除最后一个元素或者索引计算错误时,就会出现ArrayIndexOutOfBoundsException。比如下面这段错误的删除逻辑:
public class ArrayDeleteError {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
// 错误逻辑:直接删除索引为5的元素,超出数组长度
int deleteIndex = 5;
for (int i = deleteIndex; i < arr.length - 1; i++) {
arr[i] = arr[i + 1];
}
}
}
上述代码中删除索引为5的元素,而数组最大索引是4,循环条件判断时就会触发索引越界异常。
2. 空指针异常
如果操作的数组本身是null,或者删除元素后没有正确处理数组引用,就可能出现NullPointerException。比如下面的情况:
public class ArrayDeleteNullError {
public static void main(String[] args) {
int[] arr = null;
// 错误逻辑:对null数组执行删除操作
int deleteIndex = 2;
for (int i = deleteIndex; i < arr.length - 1; i++) {
arr[i] = arr[i + 1];
}
}
}
3. 删除后元素错位问题
部分开发者在删除元素时,没有正确处理后续元素的移动逻辑,或者没有更新数组的有效长度,会导致删除后数组出现重复元素或者无效值,虽然不会直接抛出异常,但属于逻辑错误。
异常修复方案
1. 修复索引越界问题
在删除元素前,先校验删除索引的合法性,确保索引在数组有效范围内,同时处理删除最后一个元素的情况。修复后的代码如下:
public class ArrayDeleteFix1 {
public static int[] deleteElement(int[] arr, int deleteIndex) {
// 校验数组是否为空
if (arr == null) {
return null;
}
// 校验删除索引是否合法
if (deleteIndex < 0 || deleteIndex >= arr.length) {
throw new IllegalArgumentException("删除索引超出数组范围");
}
// 创建新数组,长度比原数组少1
int[] newArr = new int[arr.length - 1];
// 复制删除索引之前的元素
for (int i = 0; i < deleteIndex; i++) {
newArr[i] = arr[i];
}
// 复制删除索引之后的元素
for (int i = deleteIndex; i < arr.length - 1; i++) {
newArr[i] = arr[i + 1];
}
return newArr;
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
int[] result = deleteElement(arr, 2);
for (int num : result) {
System.out.print(num + " ");
}
// 输出结果:1 2 4 5
}
}
2. 修复空指针问题
在操作数组前先判断数组引用是否为null,避免对null对象执行任何操作,也可以在方法入口处增加非空校验,不符合条件时返回明确的提示或者默认值。
public class ArrayDeleteFix2 {
public static int[] deleteElementSafe(int[] arr, int deleteIndex) {
// 先判断数组是否为null
if (arr == null) {
System.out.println("数组为空,无法执行删除操作");
return null;
}
if (arr.length == 0) {
System.out.println("数组长度为0,无法执行删除操作");
return arr;
}
if (deleteIndex < 0 || deleteIndex >= arr.length) {
System.out.println("删除索引不合法");
return arr;
}
int[] newArr = new int[arr.length - 1];
System.arraycopy(arr, 0, newArr, 0, deleteIndex);
System.arraycopy(arr, deleteIndex + 1, newArr, deleteIndex, arr.length - deleteIndex - 1);
return newArr;
}
public static void main(String[] args) {
int[] arr = null;
int[] result = deleteElementSafe(arr, 2);
// 输出:数组为空,无法执行删除操作
}
}
3. 修复元素错位问题
如果需要保留原数组的引用,同时标记有效元素长度,可以使用一个变量记录数组的有效元素个数,删除元素后更新该变量,避免访问无效位置。示例如下:
public class ArrayDeleteFix3 {
private int[] arr;
private int size; // 记录有效元素个数
public ArrayDeleteFix3(int capacity) {
arr = new int[capacity];
size = 0;
}
// 添加元素
public void add(int num) {
if (size >= arr.length) {
System.out.println("数组已满,无法添加元素");
return;
}
arr[size] = num;
size++;
}
// 删除指定索引的元素
public void delete(int deleteIndex) {
if (deleteIndex < 0 || deleteIndex >= size) {
System.out.println("删除索引不合法");
return;
}
// 移动后续元素
for (int i = deleteIndex; i < size - 1; i++) {
arr[i] = arr[i + 1];
}
size--; // 更新有效元素个数
}
// 打印有效元素
public void print() {
for (int i = 0; i < size; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
ArrayDeleteFix3 array = new ArrayDeleteFix3(5);
array.add(1);
array.add(2);
array.add(3);
array.add(4);
array.print(); // 输出:1 2 3 4
array.delete(2);
array.print(); // 输出:1 2 4
}
}
注意事项
- Java数组长度固定,删除元素本质是创建新数组或者移动元素覆盖原值,不要试图直接修改原数组的长度
- 所有涉及索引的操作都要先校验索引的合法性,避免触发索引越界异常
- 操作数组前先判断数组引用是否为null,避免空指针异常
- 如果需要频繁执行删除操作,建议使用
ArrayList等动态数组结构,其内部已经封装了完善的删除逻辑,减少手动实现出错的概率