是什么导致java.lang.ArrayIndexOutOfBoundsException,我如何防止它?

thtygnil  于 2022-09-16  发布在  Java
关注(0)|答案(26)|浏览(194)

ArrayIndexOutOfBoundsException是什么意思?我如何消除它?
以下是触发异常的代码示例:

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

whlutmcx1#

您的第一个呼叫端口应该是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循环,请这样做。)

dy2hfwbg

dy2hfwbg2#

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

wxclj1h53#

来自这篇优秀文章:ArrayIndexOutOfBoundsException in for loop
简而言之:

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

i将等于非法索引name.length,因为数组索引是基于零的。
您的代码应该是

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

jw5wzhpr4#

这意味着您试图访问数组的索引,该索引无效,因为它不在边界之间。
例如,这将初始化上界为4的原始整数数组。

int intArray[] = new int[5];

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

intArray[5];
xuo3flqw

xuo3flqw5#

ArrayIndexOutOfBoundsException的原因是什么

如果你把一个变量想象成一个可以放置值的“盒子”,那么数组就是一系列相邻的盒子,盒子的数量是一个有限的显式整数。
创建这样的阵列:

final int[] myArray = new int[5]

创建一行5个框,每个框中包含一个e1d1e。每个框都有一个索引,即一系列框中的位置。该索引从0开始,到N-1结束,其中N是数组的大小(框数)。
要从这一系列框中检索其中一个值,可以通过其索引引用它,如下所示:

myArray[3]

这将为您提供序列中第四个框的值(因为第一个框的索引为0)。
ArrayIndexOutOfBoundsException是由于试图检索不存在的“框”,通过传递高于最后一个“框”的索引或负数的索引而导致的。
在我的运行示例中,这些代码片段会产生这样的异常:

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

vulvrdjw6#

为了避免数组索引越界异常,应在何时何地使用enhanced-for语句。
主要动机(和用例)是在迭代时,不需要任何复杂的迭代步骤。您将无法使用增强的-for在数组中向后移动,或仅对其他元素进行迭代。
在这样做时,您保证不会用完要迭代的元素,并且您的[corrected]示例很容易转换。
代码如下:

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");
}
pxq42qpu

pxq42qpu7#

在代码中,您访问了从索引0到字符串数组长度的元素。name.length给出了字符串对象数组中的字符串对象数,即3,但您只能访问索引2 E1d1e,因为可以从索引0到name.length - 1访问数组,在那里您可以获得name.length对象数。
即使使用for循环,您也可以从索引零开始,并以name.length - 1结束。在数组a[n]中,您可以从a[0]访问a[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');
}
f3temu5u

f3temu5u8#

对于给定的数组,数组的长度为3(即name.length=3)。但当它存储从索引0开始的元素时,它具有最大索引2。
因此,不是“i**<=名称”。长度“你应该写”i<**名称。长度”以避免“ArrayIndexOutOfBoundsException”。

g6baxovj

g6baxovj9#

这个简单的问题到此为止,但我只想强调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

nzk0hqpo

nzk0hqpo10#

我见过的最常见的看似神秘的ArrayIndexOutOfBoundsException(即显然不是由您自己的数组处理代码引起的)是并发使用SimpleDataFormat。特别是在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"));
  }
}

如果两个线程输入SimpleDateFormat。parse()方法一起,您可能会看到ArrayIndexOutOfBoundsException。注意class javadoc for SimpleDateFormat的同步部分。
确保代码中没有任何地方以并发方式访问线程不安全类,如SimpleDataFormat,如servlet或控制器。检查servlet和控制器的所有示例变量,以查找可能的可疑对象。

7bsow1i6

7bsow1i611#

由于i<=name.length部分,您将获得ArrayIndexOutOfBoundsExceptionname.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语言规范中定义:
public final字段length,它包含阵列的组件数。length可以是正的或零。

bqjvbblv

bqjvbblv12#

这就是在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

mm9b1k5b

mm9b1k5b13#

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

zysjyyx4

zysjyyx414#

对于任何长度为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++;
}

1.一种更好的方法是对每个循环使用A,在这种方法中,程序员无需担心数组中的元素数量。

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

jtw3ybtb15#

ArrayIndexOutOfBoundsException每当出现此异常时,表示您试图使用超出其界限的数组索引,或者在外行术语中,您请求的索引超过了您初始化的索引。
为防止出现这种情况,请始终确保您没有请求数组中不存在的索引,即如果数组长度为10,则索引的范围必须在0到9之间

相关问题