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

时间:2011-04-05 15:54:04

标签: java arrays indexoutofboundsexception

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

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

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

27 个答案:

答案 0 :(得分:264)

您的第一个停靠点应该是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循环,请执行此操作。)

答案 1 :(得分:48)

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];
}

另见:


更新:根据您的代码段,

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

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

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

答案 2 :(得分:20)

简要说一下:

的最后一次迭代中
for (int i = 0; i <= name.length; i++) {

i将等于name.length这是一个非法索引,因为数组索引是从零开始的。

您的代码应该是

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

答案 3 :(得分:16)

这意味着您正在尝试访问一个无效的数组索引,因为它不在边界之间。

例如,这将使用上限4初始化一个原始整数数组。

int intArray[] = new int[5];

程序员从零开始计算。因此,例如,这将抛出ArrayIndexOutOfBoundsException,因为上限是4而不是5。

intArray[5];

答案 4 :(得分:10)

为了避免数组索引越界异常,应该在何时何地使用enhanced-for语句。

主要动机(和用例)是在迭代时,您不需要任何复杂的迭代步骤。您 不能能够使用增强型 - <div class="col-container"> <div class="col-third"> <p>content</p> </div> <div class="col-third"> <p>content</p> </div> <div class="col-third"> <p>content</p> </div> </div>在数组中向后移动或仅对每个其他元素进行迭代。

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

以下代码:

for

......等同于:

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

答案 5 :(得分:10)

导致ArrayIndexOutOfBoundsException的原因是什么?

如果您将变量视为可以放置值的“框”,则数组是一系列相邻的框,其中框的数量是有限的显式整数。

创建这样的数组:

final int[] myArray = new int[5]

创建一个包含5个框的行,每个框包含int。每个方框都有一个索引,一系列方框中的位置。该索引从0开始,以N-1结束,其中N是数组的大小(方框数)。

要从这一系列框中检索其中一个值,您可以通过索引引用它,如下所示:

myArray[3]

这将为您提供系列中第4个框的值(因为第一个框的索引为0)。

ArrayIndexOutOfBoundsException是由于尝试通过传递高于最后一个“box”的索引的索引来回溯不存在的“框”而引起的。

使用我的运行示例,这些代码片段会产生这样的异常:

myArray[5] //tries to retrieve the 6th "box" when there is only 5
myArray[-1] //just makes no sense
myArray[1337] //waay to high

如何避免ArrayIndexOutOfBoundsException

为了防止ArrayIndexOutOfBoundsException,需要考虑以下几个要点:

<强>循环

循环遍历数组时,请始终确保要检索的索引严格小于数组的长度(框数)。例如:

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

请注意<,绝不要在其中混合= ..

你可能想要做这样的事情:

for (int i = 1; i <= myArray.length; i++) {
    final int someint = myArray[i - 1]

请不要。坚持上面的那个(如果你需要使用索引)它会为你节省很多痛苦。

尽可能使用foreach:

for (int value : myArray) {

这样你就不必考虑索引了。

循环时,无论你做什么,都不要改变循环迭代器的值(这里:i)。这应该改变价值的唯一地方是保持循环。否则改变它只是冒着异常的风险,并且在大多数情况下不是必要的。

<强>检索/更新

检索数组的任意元素时,请始终检查它是否是针对数组长度的有效索引:

public Integer getArrayElement(final int index) {
    if (index < 0 || index >= myArray.length) {
        return null; //although I would much prefer an actual exception being thrown when this happens.
    }
    return myArray[index];
}

答案 6 :(得分:5)

在您的代码中,您已经访问了从索引0到字符串数组长度的元素。 name.length给出字符串对象数组中的字符串对象数,即3,但您最多只能访问索引2 name[2], 因为可以从索引0到name.length - 1访问数组,在那里可以获得name.length个对象。

即使在使用for循环时,您已经从索引零开始,您应该以{{1​​}}结尾。在数组a [n]中,您可以从[0]到[n-1]进行访问。

例如:

name.length - 1

在你的情况下:

String[] a={"str1", "str2", "str3" ..., "strn"};

for(int i=0;i<a.length()i++)
    System.out.println(a[i]);

答案 7 :(得分:4)

对于给定的数组,数组的长度为3(即name.length = 3)。但是因为它存储从索引0开始的元素,所以它具有最大索引2。

因此,您应该写'i &lt; ** name.length'而不是'i **&lt; = name.length',以避免'ArrayIndexOutOfBoundsException'。

答案 8 :(得分:3)

由于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] +'\n');
}

它在Java language specification

中定义
  

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

答案 9 :(得分:3)

这个简单的问题非常多,但我只是想强调Java中的一个新功能,它可以避免在数组索引中出现所有混淆,即使对于初学者也是如此。 Java-8已经完成了为您迭代的任务。

int[] array = new int[5];

//If you need just the items
Arrays.stream(array).forEach(item -> { println(item); });

//If you need the index as well
IntStream.range(0, array.length).forEach(index -> { println(array[index]); })

有什么好处?嗯,有一点是像英语这样的可读性。其次,您无需担心ArrayIndexOutOfBoundsException

答案 10 :(得分:3)

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

答案 11 :(得分:2)

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个项目,因此意味着name [0] =“ tom”,name [1] =“ dick”和name [2] =“ harry
  • 循环时,由于 i 可以小于或等于name.length,因此您正在尝试访问不可用的name [3]。

要解决这个问题...

  • 在您的for循环中,您可以执行<名称。长度。这样可以防止循环到名称[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(消费者操作)(需要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);

答案 12 :(得分:2)

我见过看似神秘的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和控制器的所有实例变量以查找可能的嫌疑人。

答案 13 :(得分:2)

对于多维数组,确保访问正确维度的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,为简单起见。)

答案 14 :(得分:2)

ArrayIndexOutOfBoundsException每当此异常即将到来时,这意味着您试图使用超出其范围的数组索引,或者以非专业人员的方式使用的索引所要求的数量超出了初始化的范围。

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

答案 15 :(得分:1)

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

在你的情况下

for(int i = 0; i<=name.length; i++) {
    System.out.print(name[i] +'\n'); // i goes from 0 to length, Not correct
}
当您尝试访问时,会发生

ArrayIndexOutOfBoundsException name.length索引元素,它不存在(数组索引以长度-1结尾)。只是替换&lt; = with&lt;会解决这个问题。

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

答案 16 :(得分:1)

如果您使用数组的长度来控制 for 循环的迭代,请始终记住,数组中第一项的索引为 0 。因此,数组中最后一个元素的索引比数组的长度小一个。

答案 17 :(得分:1)

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

答案 18 :(得分:1)

数组中的每个项目都称为一个元素,每个元素均通过其数字索引进行访问。如上图所示,编号以0 开头。例如,第9个元素因此将在索引8处访问。

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

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

答案 19 :(得分:1)

根据您的准则:

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');
}

答案 20 :(得分:1)

对于任何长度为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循环,在这种方法中,程序员无需担心数组中元素的数量。

    for(String str : array) {
        System.out.println(str);
    }
    

答案 21 :(得分:0)

此错误发生在运行循环超限时间。让我们考虑这样的简单示例,

class demo{
  public static void main(String a[]){

    int[] numberArray={4,8,2,3,89,5};

    int i;

    for(i=0;i<numberArray.length;i++){
        System.out.print(numberArray[i+1]+"  ");
    }
}

首先,我将一个数组初始化为'numberArray'。然后,使用for循环打印一些数组元素。当循环运行'i'时间时,打印(numberArray [i + 1]元素..(当i值为1时,打印numberArray [i + 1]元素。)..假设当i =(numberArray。 length-2),则打印数组的最后一个元素。当'i'值到达(numberArray.length-1)时,没有打印值。在这一点上,出现'ArrayIndexOutOfBoundsException'。希望您能得到idea。谢谢你!

答案 22 :(得分:0)

button.translatesAutoresizingMaskIntoConstraints = false tableView.translatesAutoresizingMaskIntoConstraints = false tableView.bottomAnchor.constraint(equalTo: button.topAnchor, constant: 8).isActive = true button.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0).isActive = true. 名称本身解释了如果您尝试访问超出数据范围范围的索引处的值,则会发生此类异常。

在您的情况下,您可以从for循环中删除等号。

ArrayIndexOutOfBoundsException

更好的选择是迭代数组:

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

答案 23 :(得分:0)

您可以在函数样式中使用Optional来避免NullPointerExceptionArrayIndexOutOfBoundsException

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

答案 24 :(得分:-1)

这里0-> tom,1-> bob,2-> harry。但是没有索引3。这里,names.length的值为3。因此,通过for循环,您正在访问索引3。因此,错误即将来临。 只是改变

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

避免

ArrayIndexOutOfBoundsException 

答案 25 :(得分:-1)

在大多数编程语言中索引都是从 0 开始的,所以你必须写成 ii<=names.length-1 i<=names.length

答案 26 :(得分:-3)

您无法迭代或存储的数据超过数组的长度。在这种情况下,您可以这样做:

for (int i = 0; i <= name.length - 1; i++) {
    // ....
}

或者这个:

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