ArrayIndexOutOfBoundsException是什么意思,我如何摆脱它?

下面是一个触发异常的代码示例:

String[] names = { "tom", "bob", "harry" };
for (int i = 0; i <= names.length; i++) {
    System.out.println(names[i]);
}

当前回答

根据贵公司守则:

String[] name = {"tom", "dick", "harry"};
for(int i = 0; i<=name.length; i++) {
  System.out.print(name[i] +'\n');
}

如果你检查 System.out.print (name.length);

你会得到3;

也就是说你的名字长度是3

你的循环从0运行到3 它应该是0到2或者1到3

回答

String[] name = {"tom", "dick", "harry"};
for(int i = 0; i<name.length; i++) {
  System.out.print(name[i] +'\n');
}

其他回答

这就是在Eclipse中抛出这种类型的异常时的样子。红色的数字表示您试图访问的索引。所以代码看起来是这样的:

myArray[5]

当您试图访问该数组中不存在的索引时,将引发此错误。如果一个数组的长度是3,

int[] intArray = new int[3];

那么唯一有效的索引是:

intArray[0]
intArray[1]
intArray[2]

如果一个数组的长度为1,

int[] intArray = new int[1];

那么唯一有效的索引是:

intArray[0]

任何等于数组长度或大于数组长度的整数都是越界的。

任何小于0的整数:都是越界的;

附注:如果您希望更好地理解数组并做一些实际练习,这里有一个视频:Java中的数组教程

我所见过的看似神秘的arrayindexoutofboundsexception最常见的情况,即显然不是由您自己的数组处理代码引起的,是SimpleDateFormat的并发使用。特别是在servlet或控制器中:

public class MyController {
  SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");

  public void handleRequest(ServletRequest req, ServletResponse res) {
    Date date = dateFormat.parse(req.getParameter("date"));
  }
}

如果两个线程一起进入SimplateDateFormat.parse()方法,你可能会看到一个ArrayIndexOutOfBoundsException异常。注意SimpleDateFormat类javadoc的同步部分。

确保代码中没有像servlet或控制器那样以并发方式访问线程不安全类(如SimpleDateFormat)的地方。检查servlet和控制器的所有实例变量,寻找可能的可疑对象。

为了避免数组索引越界异常,应该在可以的地方和时候使用增强的for语句。

主要的动机(和用例)是当您迭代时,您不需要任何复杂的迭代步骤。您不能使用增强的for在数组中向后移动或只迭代每个其他元素。

在执行此操作时,您可以保证不会耗尽要迭代的元素,并且您的[修正]示例很容易转换。

代码如下:

String[] name = {"tom", "dick", "harry"};
for(int i = 0; i< name.length; i++) {
    System.out.print(name[i] + "\n");
}

...等价于:

String[] name = {"tom", "dick", "harry"};
for(String firstName : name) {
    System.out.println(firstName + "\n");
}

你可以在函数风格中使用Optional来避免NullPointerException和ArrayIndexOutOfBoundsException:

String[] array = new String[]{"aaa", null, "ccc"};
for (int i = 0; i < 4; i++) {
    String result = Optional.ofNullable(array.length > i ? array[i] : null)
            .map(x -> x.toUpperCase()) //some operation here
            .orElse("NO_DATA");
    System.out.println(result);
}

输出:

AAA
NO_DATA
CCC
NO_DATA

我在这里看到了所有解释如何使用数组以及如何避免索引越界异常的答案。我个人不惜一切代价避免数组。我使用Collections类,这避免了必须完全处理数组下标的所有愚蠢行为。循环构造与支持更容易编写、理解和维护的代码的集合完美地工作。