什么是 java.lang.ArrayIndexOutOfBoundsException / java.lang.IndexOutOfBoundsException?
The JavaDoc http://docs.oracle.com/javase/7/docs/api/java/lang/ArrayIndexOutOfBoundsException.html简短地说:
抛出该异常表示数组已被非法访问
指数。该指数要么为负,要么大于或等于
数组的大小。
是什么导致它发生?
此异常意味着您尝试访问某个索引
数组或数组支持的列表,并且该索引不存在。
Java用途0
为基础的索引。这意味着所有索引都以0
作为
第一个元素的索引(如果它包含任何元素)。
The IndexOutOfBoundsException
消息非常明确,通常采用以下形式:
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
Where Index
是您请求的不存在的索引,并且Size
是您要索引的结构的长度。
正如你所看到的Size: 1
意味着唯一有效的索引是0
你正在询问索引中的内容1
.
例如,如果您有一个原始的Array
对象或原始类型
有效索引是0
to .length - 1
,在下面的示例中,有效索引为0, 1, 2, 3,
.
final String days[] { "Sunday", "Monday", "Tuesday" }
System.out.println(days.length); // 3
System.out.println(days[0]); // Sunday
System.out.println(days[1]); // Monday
System.out.println(days[2]); // Tuesday
System.out.println(days[3]); // java.lang.ArrayIndexOutOfBoundsException
这也适用于ArrayList
以及任何其他Collection
可能由以下支持的类Array
并允许直接访问索引。
如何避免java.lang.ArrayIndexOutOfBoundsException
/ java.lang.IndexOutOfBoundsException
?
直接通过索引访问时:
这使用Guava https://code.google.com/p/guava-libraries/转换原始原语int[]
数组到一个ImmutableList<Integer> http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ImmutableList.html。然后它使用Iterables
安全地上课
获取特定索引处的值,并在以下情况下提供默认值
该索引不存在。这里我选择了-1
来表示无效
指数值。
final List<Integer> toTen = ImmutableList.copyOf(Ints.asList(ints));
System.out.println(Iterables.get(toTen, 0, -1));
System.out.println(Iterables.get(toTen, 100, -1));
如果您由于某种原因无法使用 Guava,那么很容易推出您自己的函数来完成同样的事情。
private static <T> T get(@Nonnull final Iterable<T> iterable, final int index, @Nonnull final T missing)
{
if (index < 0) { return missing; }
if (iterable instanceof List)
{
final List<T> l = List.class.cast(iterable);
return l.size() <= index ? l.get(index) : missing;
}
else
{
final Iterator<T> iterator = iterable.iterator();
for (int i = 0; iterator.hasNext(); i++)
{
final T o = iterator.next();
if (i == index) { return o; }
}
return missing;
}
}
迭代时:
这是迭代原始数据的惯用方法Array
如果你需要
了解索引和值:
这很容易受到一次性错误这是主要原因
的一个java.lang.ArrayIndexOutOfBoundsException
:
使用传统的for-next loop:
final int ints[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (int i = 0; i < ints.length; i++)
{
System.out.format("index %d = %d", i, ints[i]);
}
使用增强型for-each loop:
这是迭代原始数据的惯用方法Array
与增强的for循环如果您不需要知道实际索引:
for (final int i : ints)
{
System.out.format("%d", i);
System.out.println();
}
使用类型安全的 Iterator:
这是迭代原始数据的安全方法Array
与增强型
for循环并跟踪当前索引并避免出现以下情况的可能性
遇到一个java.lang.ArrayIndexOutOfBoundsException
.
这使用 Guava 轻松转换int[]
对某事Iterable
每个项目都应该包含它。
final Iterator<Integer> it = Ints.asList(ints).iterator();
for (int i = 0; it.hasNext(); i++)
{
System.out.format("index %d = %d", i, it.next());
}
如果您无法使用番石榴或您的int[]
很大,你可以自己滚动ImmutableIntArrayIterator
像这样:
public class ImmutableIntArrayIterator implements Iterator<Integer>
{
private final int[] ba;
private int currentIndex;
public ImmutableIntArrayIterator(@Nonnull final int[] ba)
{
this.ba = ba;
if (this.ba.length > 0) { this.currentIndex = 0; }
else { currentIndex = -1; }
}
@Override
public boolean hasNext() { return this.currentIndex >= 0 && this.currentIndex + 1 < this.ba.length; }
@Override
public Integer next()
{
this.currentIndex++;
return this.ba[this.currentIndex];
}
@Override
public void remove() { throw new UnsupportedOperationException(); }
}
并使用与 Guava 相同的代码。
如果你绝对必须有序数对于该项目,以下是最安全的方法。
// Assume 'los' is a list of Strings
final Iterator<String> it = los.iterator();
for (int i = 0; it.hasNext(); i++)
{
System.out.format("index %d = %s", i, it.next());
}
这项技术适用于所有人可迭代对象。它不是一个index解析,但它确实为您提供了迭代中的当前位置,即使对于没有本机的事物也是如此index.
最安全的方法:
最好的方法是始终使用不可变列表 http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ImmutableList.html/Set http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ImmutableSet.html/Maps http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ImmutableMap.html来自 番石榴 作为
出色地:
final List<Integer> ili = ImmutableList.copyOf(Ints.asList(ints));
final Iterator<Integer> iit = ili.iterator();
for (int i = 0; iit.hasNext(); i++)
{
System.out.format("index %d = %d", i, iit.next());
}
Summary:
-
使用原始数组很难使用,在大多数情况下应该避免。他们有时很容易受到微妙的影响一次性错误 https://en.wikipedia.org/wiki/Off-by-one_error甚至早在那时就困扰着新程序员BASIC https://en.wikipedia.org/wiki/BASIC
-
现代 Java 惯用法使用正确的类型安全收藏品并避免使用原始array如果可能的话,结构。
-
现在几乎在所有情况下,不可变类型都是首选。
-
Guava 是现代 Java 开发不可或缺的工具包。