是什么导致java.lang.ArrayIndexOutOfBoundsException以及如何防止它?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是什么导致java.lang.ArrayIndexOutOfBoundsException以及如何防止它?相关的知识,希望对你有一定的参考价值。

什么ArrayIndexOutOfBoundsException意味着什么,我如何摆脱它?

以下是触发异常的代码示例:

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

你的第一个停靠点应该是documentation,它可以合理地解释它:

抛出以指示已使用非法索引访问数组。索引为负数或大于或等于数组的大小。

例如:

int[] array = new int[5];
int boom = array[10]; // Throws the exception

至于如何避免......嗯,不要这样做。小心你的数组索引。

人们有时遇到的一个问题是认为数组是1索引的,例如

int[] array = new int[5];
// ... populate the array here ...
for (int index = 1; index <= array.length; index++)
{
    System.out.println(array[index]);
}

这将错过第一个元素(索引0)并在索引为5时抛出异常。此处的有效索引为0-4(含)。这里正确的,惯用的for声明将是:

for (int index = 0; index < array.length; index++)

(当然,假设您需要索引。如果您可以使用增强型for循环,请执行此操作。)

另一答案

由于ArrayIndexOutOfBoundsException部分,你得到i<=name.lengthname.length返回字符串name的长度,即3。因此,当您尝试访问name[3]时,它是非法的并抛出异常。

已解决的代码:

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

它在Java language specification中定义:

public final字段length,包含数组的组件数。 length可能是正数或零。

另一答案

Array index out of bounds exception

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

myArray[5]

当您尝试访问该数组中不存在的索引时,将引发该错误。如果数组的长度为3,

int[] intArray = new int[3];

那么唯一有效的索引是:

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

如果数组的长度为1,

int[] intArray = new int[1];

那么唯一有效的索引是:

intArray[0]

任何等于数组长度或大于数组的整数:超出范围。

任何小于0的整数都是超出范围的;

P.S。:如果您希望更好地理解阵列并做一些实际练习,那么这里有一个视频:tutorial on arrays in Java

另一答案

我见过看似神秘的ArrayIndexOutOfBoundsExceptions的最常见的情况,即显然不是由你自己的数组处理代码引起的,是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。请注意class javadoc for SimpleDateFormat的同步部分。

确保代码中没有以并发方式访问线程不安全类(如SimpleDateFormat)的位置,例如在servlet或控制器中。检查servlet和控制器的所有实例变量以查找可能的嫌疑人。

另一答案

对于多维数组,确保访问正确维度的length属性可能很棘手。以下面的代码为例:

int [][][] a  = new int [2][3][4];

for(int i = 0; i < a.length; i++){
    for(int j = 0; j < a[i].length; j++){
        for(int k = 0; k < a[j].length; k++){
            System.out.print(a[i][j][k]);
        }
        System.out.println();
    }
    System.out.println();
}

每个维度都有不同的长度,因此微妙的错误是中间和内部循环使用相同维度的length属性(因为a[i].lengtha[j].length相同)。

相反,内环应使用a[i][j].length(或简称为a[0][0].length)。

另一答案

ArrayIndexOutOfBoundsException每当发生此异常时,它意味着您正在尝试使用超出其范围的数组索引,或者您正在请求超过初始化的非专业术语。

为了防止这种情况,请始终确保您没有请求数组中不存在的索引,即如果数组长度为10,则索引必须介于0到9之间

另一答案

ArrayIndexOutOfBounds意味着您正在尝试索引未分配的数组中的位置。

在这种情况下:

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
  • name.length为3,因为已使用3个String对象定义了数组。
  • 当访问数组的内容时,位置从0开始。由于有3个项目,它将表示名称[0] =“tom”,名称[1] =“dick”和名称[2] =“哈里
  • 当你循环时,因为我可以小于或等于name.length,你试图访问不可用的名称[3]。

绕过这个......

  • 在你的for循环中,你可以做<name.length。这将阻止循环到名称[3],而是停止在名称[2] for(int i = 0; i<name.length; i++)
  • 每个循环使用一个 String[] name = { "tom", "dick", "harry" }; for(String n : name) { System.out.println(n); }
  • 使用list.forEach(Consumer Action)(需要Java8) String[] name = { "tom", "dick", "harry" }; Arrays.asList(name).forEach(System.out::println);
  • 将数组转换为流 - 如果您想对数组执行其他“操作”,这是一个不错的选择,例如过滤,转换文本,转换为地图等(需要Java8) String[] name = { "tom", "dick", "harry" }; --- Arrays.asList(name).stream().forEach(System.out::println); --- Stream.of(name).forEach(System.out::println);
另一答案

ArrayIndexOutOfBoundsException表示您正在尝试访问不存在或超出此数组范围的数组的索引。数组索引从0开始,以长度结束 - 1。

在你的情况下

for(int i = 0; i<=name.length; i++) {
    System.out.print(name[i] +'
'); // i goes from 0 to length, Not correct
}

当您尝试访问不存在的name.length索引元素时,会发生ArrayIndexOutOfBoundsException(数组索引以长度-1结尾)。只需用<替换<=就可以解决这个问题。

for(int i = 0; i < name.length; i++) {
    System.out.print(name[i] +'
');  // i goes from 0 to length - 1, Correct
}
另一答案

对于任何长度为n的数组,数组的元素将具有从0到n-1的索引。

如果您的程序试图访问任何数组索引大于n-1的元素(或内存),那么Java将抛出ArrayIndexOutOfBoundsException

所以这里有两个我们可以在程序中使用的解决方案

  1. 维持计数: for(int count = 0; count < array.length; count++) { System.out.println(array[count]); } 或者像其他一些循环语句 int count = 0; while(count < array.length) { System.out.println(array[count]); count++; }
  2. 对于每个循环更好的方法是,在这种方法中,程序员无需担心数组中的元素数量。 for(String str : array) { System.out.println(str); }
另一答案

根据您的准则:

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

如果检查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] +'
');
}
另一答案

数组中的每个项称为一个元素,每个元素都由其数字索引访问。如上图所示,编号从0开始。例如,第9个元素将在索引8处访问。

抛出IndexOutOfBoundsException以指示某种索引(例如数组,字符串或向量)超出范围。

任何数组X都可以从[0到(X.length - 1)]访问

另一答案
if (index < 0 || index >= array.length) {
    // Don't use this index. This is out of bounds (borders, limits, whatever).
} else {
    // Yes, you can safely use this index. The index is present in the array.
    Object element = array[index];
}

See also:


更新:根据您的代码段,

for (int i = 0; i<=name.length; i++) {

索引包含数组的长度。这是出界的。你需要用<=替换<

for (int i = 0; i < name.length; i++) {
另一答案

我在这里看到所有答案,解释了如何使用数组以及如何避免索引超出范围的异常。我个人不惜一切代价避免使用阵列。我使用Collections类,它避免了完全处理数组索引的所有愚蠢。循环结构可以很好地处理支持代码的集合,这些代码更易于编写,理解和维护。