ArrayIndexOutOfBoundsException
是什么意思,我该如何摆脱?
这是触发异常的代码示例:
String[] names = { "tom", "bob", "harry" };
for (int i = 0; i <= names.length; i++) {
System.out.println(names[i]);
}
您的第一个通话端口应为文档< / a>对此进行了合理清晰的解释:
抛出该错误指示已使用非法索引访问了数组。索引为负或大于或等于数组的大小。
例如:
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),并在index为5时引发异常。此处的有效索引为0-4(含0和4)。正确,惯用的for
语句为:
for (int index = 0; index < array.length; index++)
(当然,这是假设您需要 索引。如果您可以使用增强的for循环,请这样做。)
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++) {
这篇出色的文章中: for循环中的ArrayIndexOutOfBoundsException
简而言之:
在
的最后一次迭代中for (int i = 0; i <= name.length; i++) {
i
将等于name.length
,这是一个非法索引,因为数组索引是从零开始的。
您的代码应阅读
for (int i = 0; i < name.length; i++)
^
这意味着您正在尝试访问无效的数组索引,因为它不在边界之间。
例如,这将初始化一个上限为4的原始整数数组。
int intArray[] = new int[5];
程序员从零开始计数。因此,例如,由于上限为4而不是5,因此会抛出ArrayIndexOutOfBoundsException
。
intArray[5];
为避免数组索引越界异常,应使用在何时何地可以增强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");
}
是什么原因导致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
如何避免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];
}
在您的代码中,您访问了从索引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');
}
对于给定的数组,数组的长度为3(即name.length = 3)。但是由于它存储从索引0开始的元素,因此具有最大索引2。
因此,应使用" i <** name.length"代替" i ** <= name.length",以避免" ArrayIndexOutOfBoundsException"。
这个简单的问题就这么多了,但是我只是想强调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
由于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中定义语言规范:
publicfinal
字段length
,其中包含数组的组件数。length
可以是正数或零。
这就是在Eclipse中抛出这种异常时的样子。红色数字表示您尝试访问的索引。所以代码看起来像这样:
myArray[5]
当您尝试访问该数组中不存在的索引时,将引发错误。如果数组的长度为3,
int[] intArray = new int[3];
那么唯一的有效索引是:
intArray[0]
intArray[1]
intArray[2]
如果数组的长度为1,
int[] intArray = new int[1];
那么唯一的有效索引是:
intArray[0]
任何等于数组长度或大于数组长度的整数:超出范围。
任何小于0的整数:超出范围;
PS:如果您希望更好地理解数组并进行一些实际练习,请在此处观看视频:有关Java中的数组的教程
对于多维数组,确保访问正确维的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
)。 / p>
对于看似神秘的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。请注意 SimpleDateFormat类javadoc的同步部分。
请确保您的代码中没有任何地方可以以并发方式(例如,在servlet或控制器中)访问诸如SimpleDateFormat之类的线程不安全类。检查您的Servlet和控制器的所有实例变量,以查找可能的可疑对象。
ArrayIndexOutOfBoundsException每当此异常即将到来时,这意味着您试图使用超出其范围的数组索引,或者以非专业人员的方式使用的索引所要求的数量比初始化的要多。
为防止这种情况,请始终确保您不请求数组中不存在的索引,即,如果数组长度为10,则索引范围必须在0到9之间
ArrayIndexOutOfBounds表示您试图索引未分配的数组中的位置。
在这种情况下:
String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
System.out.println(name[i]);
}
要解决这个问题...
在for循环中,您可以执行<名称。长度。这样可以防止循环到名称[3],而是停在名称[2]>名称。长度。这样可以防止循环到名称[3],而是停在名称[2]>
for(inti=0;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);
将数组转换为流-如果要对数组执行其他``操作'',例如,这是一个不错的选择过滤,转换文本,转换为地图等(需要Java8)
String[]name={"tom","dick","harry"};--- Arrays.asList(name).stream()。forEach(System.out :: println); --- Stream.of(name).forEach(System.out :: println);
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
}
ArrayIndexOutOfBoundsException
在您尝试访问不存在的name.length索引元素时发生(数组索引以长度-1结尾)。只需将<=替换为<即可解决此问题。>即可解决此问题。>
for(int i = 0; i < name.length; i++) {
System.out.print(name[i] +'\n'); // i goes from 0 to length - 1, Correct
}
对于长度为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(String str : array) {
System.out.println(str);
}
根据您的代码:
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"运行
答案
String[] name = {"tom", "dick", "harry"};
for(int i = 0; i<name.length; i++) {
System.out.print(name[i] +'\n');
}
数组中的每个项目都称为一个元素,每个元素都可以通过其数字索引进行访问。如上图所示,编号从0 开始。例如,第9个元素因此将在索引8处访问。
抛出IndexOutOfBoundsException表示某种索引(例如数组,字符串或向量)超出范围。
任何数组X均可从[0到(X.length-1)]访问
我在这里看到所有答案,解释了如何使用数组以及如何避免索引超出范围异常。我个人不惜一切代价避免使用数组。我使用Collections类,这避免了必须完全处理数组索引的所有愚蠢行为。循环结构可与支持代码的集合完美配合,这些代码更易于编写,理解和维护。
如果您使用数组的长度控制 for 循环的迭代,请始终记住,数组中第一项的索引为 0 。因此,数组中最后一个元素的索引比数组的长度小一个。
ArrayIndexOutOfBoundsException
名称本身说明,如果您尝试访问索引超出数组大小范围的值,则会发生这种异常。
对于您而言,您只需从for循环中删除等号即可。
for(int i = 0; i<name.length; i++)
更好的选择是迭代数组:
for(String i : name )
System.out.println(i);
此错误发生在运行循环超限时间。让我们考虑这样的简单示例,
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'。希望您能得到idea。谢谢你!
您可以在函数样式中使用Optional来避免NullPointerException
和ArrayIndexOutOfBoundsException
:
String[] array = new String[]{"aaa", null, "ccc"};
for (int i = 0; i < 4; i++) {
String result = Optional.ofNullable(array.length > i ? array[i] : null)
.map(x -> x.toUpperCase()) //some operation here
.orElse("NO_DATA");
System.out.println(result);
}
输出:
AAA
NO_DATA
CCC
NO_DATA
您不能迭代或存储比数组长度更多的数据。在这种情况下,您可以这样:
for (int i = 0; i <= name.length - 1; i++) {
// ....
}
或者这个:
for (int i = 0; i < name.length; i++) {
// ...
}