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];
}
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];
}
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]); })
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();
}
public class MyController {
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
public void handleRequest(ServletRequest req, ServletResponse res) {
Date date = dateFormat.parse(req.getParameter("date"));
}
}
23 回答
您的第一个停靠点应该是documentation,它可以相当清楚地解释它:
例如:
至于如何避免......嗯,不要这样做 . 小心你的数组索引 .
人们有时遇到的一个问题是认为数组是1索引的,例如
这将错过第一个元素(索引0)并在索引为5时抛出异常 . 此处的有效索引为0-4(含) . 这里正确的,惯用的
for
语句将是:(当然,假设您需要索引 . 如果您可以使用增强型for循环,请执行此操作 . )
另见:
Update :根据您的代码段,
索引包含数组的长度 . 这是出界的 . 您需要将
<=
替换为<
.简而言之:
在最后一次迭代中
i
将等于name.length
这是一个非法索引,因为数组索引是从零开始的 .你的代码应该阅读
这意味着您正在尝试访问一个无效的数组索引,因为它不在边界之间 .
例如,这将初始化具有上限4的原始整数数组 .
程序员从零开始计算 . 例如,这将抛出一个
ArrayIndexOutOfBoundsException
,因为上限是4而不是5 .为了避免数组索引越界异常,应该在何时何地使用enhanced-for语句 .
主要动机(和用例)是在迭代时,您不需要任何复杂的迭代步骤 . 您将无法使用增强型
for
在数组中向后移动或仅在每个其他元素上进行迭代 .保证在执行此操作时不会耗尽元素进行迭代,并且您的[更正]示例很容易转换 .
代码如下:
......等同于:
您无法迭代或存储的数据超过数组的长度 . 在这种情况下,您可以这样做:
或这个:
What causes ArrayIndexOutOfBoundsException?
如果您将变量视为可以放置值的“框”,则数组是一系列相邻的框,其中框的数量是有限的显式整数 .
像这样创建一个数组:
创建一个5行的行,每行包含一个
int
. 每个方框都有一个索引,一系列方框中的位置 . 该索引从0开始,以N-1结束,其中N是数组的大小(方框数) .要从这一系列框中检索其中一个值,您可以通过其索引引用它,如下所示:
这将为您提供系列中第4个框的值(因为第一个框的索引为0) .
ArrayIndexOutOfBoundsException
是由于尝试通过传递高于最后"box"的索引的索引或负数来检索不存在的"box"而引起的 .使用我的运行示例,这些代码片段会产生这样的异常:
How to avoid ArrayIndexOutOfBoundsException
为了防止
ArrayIndexOutOfBoundsException
,需要考虑以下几个要点:Looping
循环遍历数组时,请始终确保要检索的索引严格小于数组的长度(框数) . 例如:
注意
<
,从不在那里混合=
..你可能想要做这样的事情:
只是不要 . 坚持上面的那个(如果你需要使用索引)它会为你节省很多痛苦 .
尽可能使用foreach:
这样您就不必考虑索引了 .
在循环时,无论你做什么,都不要改变循环迭代器的值(这里:
i
) . 这应该改变 Value 的唯一地方是保持循环 . 否则改变它只是冒着异常的风险,并且在大多数情况下是不必要的 .Retrieval/update
检索数组的任意元素时,请始终检查它是否是针对数组长度的有效索引:
在您的代码中,您已经访问了从索引0到字符串数组长度的元素 .
name.length
给出了字符串对象数组中的字符串对象数,即3,但是您只能访问索引2name[2]
,因为可以从索引0到name.length - 1
访问该数组,在这里您可以获得name.length
个对象 .即使在使用
for
循环时,您已经从索引零开始,您应该以name.length - 1
结束 . 在数组a [n]中,您可以从[0]到[n-1]进行访问 .例如:
在你的情况下:
对于给定的数组,数组的长度为3(即name.length = 3) . 但是因为它存储从索引0开始的元素,所以它具有最大索引2 .
所以,而不是'i ** <= name.length' you should write 'i <** name.length' to avoid ' ArrayIndexOutOfBoundsException' .
这个简单的问题非常多,但我只是想强调一下Java中的一个新功能,它将避免在数组索引中出现所有混淆,即使对于初学者也是如此 . Java-8已经完成了为您迭代的任务 .
有什么好处?嗯,有一点是像英语这样的可读性 . 其次,你不必担心
ArrayIndexOutOfBoundsException
由于
i<=name.length
部分,你得到ArrayIndexOutOfBoundsException
.name.length
返回字符串name
的长度,即3.当您尝试访问name[3]
时,它是非法的并抛出异常 .已解决的代码:
它在Java language specification中定义:
这就是在Eclipse中抛出这种类型的异常时的样子 . 红色数字表示您尝试访问的索引 . 所以代码看起来像这样:
当您尝试访问该数组中不存在的索引时,将引发该错误 . 如果数组的长度为3,
那么唯一有效的索引是:
如果数组的长度为1,
那么唯一有效的索引是:
任何等于数组长度或大于数组的整数:超出范围 .
任何小于0的整数都是超出范围的;
P.S . :如果您希望更好地理解阵列并进行一些实际练习,那么这里有一个视频:tutorial on arrays in Java
对于多维数组,确保访问正确维度的
length
属性可能很棘手 . 以下面的代码为例:每个维度都有不同的长度,因此细微的错误是中间和内部循环使用相同维度的
length
属性(因为a[i].length
与a[j].length
相同) .相反,内部循环应使用
a[i][j].length
(或简称为a[0][0].length
) .ArrayIndexOutOfBoundsException每当出现此异常时,它意味着您正在尝试使用超出其范围的数组索引,或者您要求的数据超出初始化范围 .
为了防止这种情况,请始终确保您没有请求数组中不存在的索引,即如果数组长度为10,那么您的索引必须介于0到9之间
ArrayIndexOutOfBounds意味着您正在尝试索引未分配的数组中的位置 .
在这种情况下:
name.length为3,因为已使用3个String对象定义了数组 .
当访问数组的内容时,位置从0开始 . 由于有3个项目,它将表示名称[0] = "tom",名称[1] = "dick"和名称[2] =“哈里
当你循环时,因为我可以小于或等于name.length,你试图访问不可用的名称[3] .
绕过这个......
for(int i = 0; i<name.length; i++)
String[] name = { "tom", "dick", "harry" }; for(String n : name) { System.out.println(n); }
String[] name = { "tom", "dick", "harry" }; Arrays.asList(name).forEach(System.out::println);
String[] name = { "tom", "dick", "harry" }; --- Arrays.asList(name).stream().forEach(System.out::println); --- Stream.of(name).forEach(System.out::println);
ArrayIndexOutOfBoundsException
表示您正在尝试访问不存在或超出此数组范围的数组的索引 . 数组索引从 0 开始,到 length - 1 结束 .在你的情况下
当您尝试访问不存在的name.length索引元素时,会发生
ArrayIndexOutOfBoundsException
(数组索引的长度为-1) . 只需用<替换<=就可以解决这个问题 .我见过看似神秘的ArrayIndexOutOfBoundsExceptions的最常见的情况,即显然不是由你自己的数组处理代码引起的,是SimpleDateFormat的并发使用 . 特别是在servlet或控制器中:
如果两个线程一起进入SimplateDateFormat.parse()方法,您可能会看到ArrayIndexOutOfBoundsException . 请注意class javadoc for SimpleDateFormat的同步部分 .
确保代码中没有以并发方式访问线程不安全类(如SimpleDateFormat)的位置,例如在servlet或控制器中 . 检查servlet和控制器的所有实例变量以查找可能的嫌疑人 .
For any array of length n, elements of the array will have an index from 0 to n-1.
如果您的程序试图访问任何数组索引大于n-1的元素(或内存),那么Java将抛出 ArrayIndexOutOfBoundsException
所以这里有两个我们可以在程序中使用的解决方案
或者像其他一些循环语句
数组中的每个项称为元素,每个元素都由其数字索引访问 . 如前所示插图, numbering begins with 0 . 例如,第9个元素将在索引8处访问 .
抛出IndexOutOfBoundsException以指示某种索引(例如数组,字符串或向量)超出范围 .
任何数组X都可以从[0到(X.length - 1)]访问
我在这里看到所有答案,解释了如何使用数组以及如何避免索引超出范围的异常 . 我个人不惜一切代价避免使用阵列 . 我使用Collections类,它避免了完全处理数组索引的所有愚蠢 . 循环结构可以很好地处理支持代码的集合,这些代码更易于编写,理解和维护 .
根据您的准则:
如果检查System.out.print(name.length);
你会得到3;
这意味着你的名字长度是3
你的循环从0到3运行,它应该运行“0到2”或“1到3”
Answer
ArrayIndexOutOfBoundsException
name本身解释了如果您尝试访问超出Array size范围的索引处的值,则会发生此类异常 .在您的情况下,您可以从for循环中删除等号 .
更好的选择是迭代一个数组:
在运行循环超过时间时会发生此错误 . 让我们考虑这样的简单示例,
首先,我将数组初始化为'numberArray' . 然后,使用for循环打印一些数组元素 . 当循环运行'i'时,打印(numberArray [i 1]元素..(当i值为1时,打印numberArray [i 1]元素 . )..假设,当i =(numberArray.length- 2),数组的最后一个元素被打印..当'i'值进入(numberArray.length-1)时,没有打印值 . 在这一点上,发生'ArrayIndexOutOfBoundsException' . 我希望你能得到想法 . 谢谢 !