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

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

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

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

bqjvbblv16#

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

7bsow1i6

7bsow1i617#

由于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可以是正的或零。

nzk0hqpo

nzk0hqpo18#

我见过的最常见的看似神秘的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和控制器的所有示例变量,以查找可能的可疑对象。

g6baxovj

g6baxovj19#

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

f3temu5u

f3temu5u20#

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

pxq42qpu

pxq42qpu21#

在代码中,您访问了从索引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');
}
vulvrdjw

vulvrdjw22#

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

xuo3flqw23#

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

jw5wzhpr24#

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

int intArray[] = new int[5];

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

intArray[5];
wxclj1h5

wxclj1h525#

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

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

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

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

dy2hfwbg26#

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

相关问题