什么导致java.lang.ArrayIndexOutOfBoundsException,我该如何防止它?
 ArrayIndexOutOfBoundsException是什么意思,我该如何摆脱它? 
以下是触发exception的代码示例:
 String[] name = {"tom", "dick", "harry"}; for(int i = 0; i<=name.length; i++) { System.out.print(name[i] +'\n'); } 
	
你的第一个停靠港应该是合理清楚地解释它的文件 :
抛出以指示已经使用非法索引访问数组。 该索引是否定的或者大于或等于数组的大小。
举个例子:
 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时抛出一个exception。这里的有效索引是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]; } 
也可以看看:
- Java教程 – 语言基础 – 数组
更新 :根据你的代码片段,
 for(int i = 0; i<=name.length; i++) { 
 索引包含数组的长度。 这是超出界限的。 你需要用<=replace<= 。 
 for(int i = 0; i < name.length; i++) { 
简要说一下:
在最后一次迭代中
 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]; 
 程序员从零开始计数。 所以这个例子会抛出一个ArrayIndexOutOfBoundsException因为上限是4而不是5。 
 intArray[5]; 
 为了避免数组索引超出范围的exception,应该在何时何地可以使用enhanced- 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 ? 
如果你把一个variables想象成一个可以放置一个值的“盒子”,那么一个数组就是一系列放在彼此旁边的盒子,盒子的数量是一个有限的显式整数。
像这样创build一个数组:
 final int[] myArray = new int[5] 
 创build一行5个框,每个框持有一个int 。 每个方框都有一个索引,一系列方框中的一个位置。 该索引从0开始,并在N-1结束,其中N是数组的大小(框的数量)。 
要从这一系列框中检索其中一个值,可以通过索引来引用它,如下所示:
 myArray[3] 
这将给你的系列中的第四个框的值(因为第一个框的索引为0)。
  ArrayIndexOutOfBoundsException是由于尝试通过传递比最后一个“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++) { 
 注意< ,从来没有在那里混合a = .. 
你可能想要做这样的事情:
 for (int i = 1; i <= myArray.length; i++) { final int someint = myArray[i - 1] 
只是不要。 坚持上面的(如果你需要使用索引),它会为您节省很多的痛苦。
在可能的情况下,使用foreach:
 for (int value : myArray) { 
这样你就不必考虑索引了。
 循环时,不pipe你做什么,都不要改变循环迭代器的值(这里是: 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到string数组长度的元素。  name.length给出了string对象数组中的string对象的数量,即3,但是只能访问到索引2的name[2] ,因为数组可以从索引0访问到name.length - 1 , name.length对象的数量。 
 即使在使用for循环的时候,你已经开始使用索引零,你应该以name.length - 1结束。 在数组a [n]中,您可以访问从[0]到[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'); } 
对于这个简单的问题,这么多,但我只是想强调一个Java中的新function,这将避免所有在数组中的索引混淆,即使是初学者。 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 
我所见过的看起来很神秘的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")); } } 
如果两个线程一起inputSimplateDateFormat.parse()方法,您可能会看到ArrayIndexOutOfBoundsException。 请注意SimpleDateFormat的类javadoc的同步部分。
确保在你的代码中没有任何地方是像servlet或控制器那样以并发的方式访问像SimpleDateFormat这样的线程不安全的类。 检查您的servlets程序和控制器的所有实例variables可能的嫌疑人。
对于任何长度为n的数组,数组的元素将具有从0到n-1的索引。
如果你的程序试图访问数组索引大于n-1的任何元素(或内存),那么java将抛出ArrayIndexOutOfBoundsException
所以这里有两个解决scheme,我们可以在程序中使用
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++; } 
2.使用For Each循环的方法,在这个方法中,程序员不需要为数组中元素的数量而烦恼。
 for(String str : array) { System.out.println(str); } 
 由于i<=name.length部分,您将获得ArrayIndexOutOfBoundsException 。  name.length返回stringname的长度,即3。因此当你试图访问name[3] ,它的非法并抛出exception。 
解决的代码:
 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可能是正数或零。
  
 
这就是这种types的exception在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如果你对数组有更好的理解并做一些实际的练习,这里有一个video: 关于java中数组的教程
您不能迭代或存储比数组长度更多的数据。 在这种情况下,你可以这样做:
 for (int i = 0; i <= name.length - 1; i++) { // .... } 
或这个:
 for (int i = 0; i < name.length; i++) { // ... }