首页 文章

导致java.lang.ArrayIndexOutOfBoundsException的原因是什么以及如何阻止它?

提问于
浏览
226

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

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

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

23 回答

  • 1

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

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

    另见:


    Update :根据您的代码段,

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

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

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

    简而言之:

    在最后一次迭代中

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

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

    你的代码应该阅读

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

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

    例如,这将初始化具有上限4的原始整数数组 .

    int intArray[] = new int[5];
    

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

    intArray[5];
    
  • 0

    为了避免数组索引越界异常,应该在何时何地使用enhanced-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");
    }
    
  • -1

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

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

    或这个:

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

    What causes ArrayIndexOutOfBoundsException?

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

    像这样创建一个数组:

    final int[] myArray = new int[5]
    

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

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

    myArray[3]
    

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

    ArrayIndexOutOfBoundsException 是由于尝试通过传递高于最后"box"的索引的索引或负数来检索不存在的"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
    

    How to avoid ArrayIndexOutOfBoundsException

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

    Looping

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

    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 ) . 这应该改变 Value 的唯一地方是保持循环 . 否则改变它只是冒着异常的风险,并且在大多数情况下是不必要的 .

    Retrieval/update

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

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

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

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

    例如:

    String[] a={"str1", "str2", str3" ..., "strn"};
    
    for(int i=0;i<a.length()i++)
        System.out.println(a[i]);
    

    在你的情况下:

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

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

    所以,而不是'i ** <= name.length' you should write 'i <** name.length' to avoid ' ArrayIndexOutOfBoundsException' .

  • 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

  • 0

    由于 i<=name.length 部分,你得到 ArrayIndexOutOfBoundsException . name.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字段长度,包含数组的组件数 . 长度可以是正数或零 .

  • 2

    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

  • 0

    对于多维数组,确保访问正确维度的 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 ) .

  • 8

    ArrayIndexOutOfBoundsException每当出现此异常时,它意味着您正在尝试使用超出其范围的数组索引,或者您要求的数据超出初始化范围 .

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

  • 4

    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++)

    • 为每个循环使用a

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

    • 将数组转换为流 - 如果您想对数组执行其他“操作”,这是一个不错的选择,例如过滤,转换文本,转换为 Map 等(需要Java8)

    String[] name = { "tom", "dick", "harry" }; --- Arrays.asList(name).stream().forEach(System.out::println); --- Stream.of(name).forEach(System.out::println);

  • 2

    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
    }
    

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

    for(int i = 0; i < name.length; i++) {
        System.out.print(name[i] +'\n');  // i goes from 0 to length - 1, Correct
    }
    
  • 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和控制器的所有实例变量以查找可能的嫌疑人 .

  • 0

    For any array of length n, elements of the array will have an index from 0 to n-1.

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

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

    • 维持计数:
    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++;
    }
    
    • 更好的方法是为每个循环使用a,在这种方法中,程序员无需担心数组中的元素数量 .
    for(String str : array) {
        System.out.println(str);
    }
    
  • 0

    数组中的每个项称为元素,每个元素都由其数字索引访问 . 如前所示插图, numbering begins with 0 . 例如,第9个元素将在索引8处访问 .

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

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

  • -3

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

  • -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”

    Answer

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

    ArrayIndexOutOfBoundsException name本身解释了如果您尝试访问超出Array size范围的索引处的值,则会发生此类异常 .

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

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

    更好的选择是迭代一个数组:

    for(String i : name )
          System.out.println(i);
    
  • -1

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

    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' . 我希望你能得到想法 . 谢谢 !

相关问题