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

f2uvfpb9  于 2021-06-30  发布在  Java
关注(0)|答案(17)|浏览(364)

是什么 ArrayIndexOutOfBoundsException 我的意思是我该怎么摆脱它?
下面是触发异常的代码示例:

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

fslejnso1#

arrayindexoutofbounds意味着您正在尝试索引未分配的数组中的位置。
在这种情况下:

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

name.length是3,因为数组是用3个字符串对象定义的。
访问数组内容时,位置从0开始。因为有3个条目,所以它的意思是name[0]=“汤姆”,name[1]=“迪克”和name[2]=“哈里”
循环时,由于i可以小于或等于name.length,因此您正在尝试访问name[3],而name[3]不可用。
为了避开这个。。。
在for循环中,可以执行i<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(使用者操作)(需要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);

8yoxcaq7

8yoxcaq72#

什么原因 ArrayIndexOutOfBoundsException ?
如果把一个变量看作一个可以放置值的“盒子”,那么数组就是一系列相邻放置的盒子,盒子的数量是一个有限的显式整数。
创建如下数组:

final int[] myArray = new int[5]

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

myArray[3]

这将为您提供系列中第四个框的值(因为第一个框的索引为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

如何避免 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];
}
bqucvtff

bqucvtff3#

为了避免数组索引越界异常,应该使用增强的- 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");
}
iaqfqrcu

iaqfqrcu4#

对于看似神秘的arrayindexoutofboundseceptions(即显然不是由您自己的数组处理代码引起的),我见过的最常见的情况是并发使用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。注意simpledateformat类javadoc的同步部分。
确保在您的代码中没有以servlet或控制器等并发方式访问simpledateformat之类的线程不安全类的地方。检查servlet和控制器的所有示例变量以查找可能的嫌疑犯。

txu3uszq

txu3uszq5#

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

int intArray[] = new int[5];

程序员从零开始计数。所以这个例子会抛出一个 ArrayIndexOutOfBoundsException 因为上限是4而不是5。

intArray[5];
13z8s7eq

13z8s7eq6#

arrayindexoutofboundsexception每当出现此异常时,它意味着您试图使用超出其界限的数组索引,或者在外行术语中,您请求的索引比您初始化的要多。
为了避免这种情况,请始终确保您没有请求数组中不存在的索引,即,如果数组长度为10,则索引的范围必须介于0到9之间

u2nhd7ah

u2nhd7ah7#

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

svdrlsy4

svdrlsy48#

来自这篇优秀的文章:for循环中的arrayindexoutofboundsexception
简而言之:
在的最后一次迭代中

for (int i = 0; i <= name.length; i++) {
``` `i` 将等于 `name.length` 这是非法索引,因为数组索引是基于零的。
你的代码应该是

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

cygmwpex

cygmwpex9#

在代码中,您访问了从索引0到字符串数组长度的元素。 name.length 给出字符串对象数组中字符串对象的数目,即3,但最多只能访问索引2 name[2] ,因为可以从索引0到 name.length - 1 你去哪了 name.length 对象数。
即使在使用 for 循环以索引0开始,应该以 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');
}
pcrecxhr

pcrecxhr10#

您的第一个停靠港应该是合理清楚地解释它的文档:
抛出以指示已使用非法索引访问数组。索引为负数或大于或等于数组的大小。
例如:

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循环,请这样做。)

fivyi3re

fivyi3re11#

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

另请参见:

java教程-语言基础-数组
更新:根据你的代码片段,

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

索引包含数组长度。这是不允许的。你需要替换 <=< .

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

9avjhtql12#

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

mm5n2pyu

mm5n2pyu13#

对于多维数组,确保访问 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].length 与相同 a[j].length ).
相反,内部循环应该使用 a[i][j].length (或 a[0][0].length ,为简单起见)。

yh2wf1be

yh2wf1be14#


这就是在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:如果您想更好地理解数组并做一些实践练习,这里有一个视频:java数组教程

n3h0vuf2

n3h0vuf215#

对于长度为n的任何数组,数组元素的索引范围为0到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++;
}

在这种方法中,更好的方法是使用for-each循环

相关问题