如何避免 ArrayIndexOutOfBoundsException 或 IndexOutOfBoundsException? [英] How to avoid ArrayIndexOutOfBoundsException or IndexOutOfBoundsException?

查看:21
本文介绍了如何避免 ArrayIndexOutOfBoundsException 或 IndexOutOfBoundsException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果您的问题是我的代码中出现 java.lang.ArrayIndexOutOfBoundsException,但我不明白为什么会这样.这是什么意思,我该如何避免?

<块引用>

这是关于此的最全面的规范信息集合java.lang.ArrayIndexOutOfBoundsException 主题以及 java.lang.IndexOutOfBoundsException.

有很多这样的问题,所有这些问题的答案要么含糊不清,要么大部分都是非常具体的,并且针对手头的问题进行了本地化,并且没有解决在所有情况下都完全相同的根本原因.

<小时><块引用>

如果您看到一个属于这种一般情况的内容,而不是用更多重复的专业内容来回答它,而是将其标记为该内容的重复.

解决方案

java.lang.ArrayIndexOutOfBoundsException/java.lang.IndexOutOfBoundsException 是什么?

JavaDoc 简要说明:

<块引用>

抛出表示一个数组被非法访问指数.索引为负或大于或等于数组的大小.

是什么导致它发生?

<块引用>

这个异常意味着你试图访问一个索引数组或数组支持的列表并且该索引不存在.

Java 使用基于 0 的索引.这意味着所有索引都以 0 作为开头如果第一个元素包含任何元素,则为第一个元素的索引.

IndexOutOfBoundsException 消息非常明确,通常采用以下形式:

java.lang.IndexOutOfBoundsException:索引:1,大小:1

其中 Index 是您请求的不存在的索引,Size 是您要索引到的结构的长度.

如您所见,Size: 1 表示唯一有效的索引是 0,并且您正在询问索引 1 处的内容.

<块引用>

例如,如果您有对象或原始类型的原始 Array有效索引为 0.length - 1,在以下示例中,有效索引为 0,1,2,3,.

final String days[] { "Sunday", "Monday", "Tuesday" }System.out.println(days.length);//3System.out.println(天[0]);//星期日System.out.println(天[1]);//周一System.out.println(天[2]);//周二System.out.println(天[3]);//java.lang.ArrayIndexOutOfBoundsException

这也适用于 ArrayList 以及任何其他 Collection 类,这些类可能由 Array 支持并允许直接访问索引.

如何避免java.lang.ArrayIndexOutOfBoundsException/java.lang.IndexOutOfBoundsException?

直接通过索引访问时:

<块引用>

这使用 Guava 来转换原始原语 int[] 数组到一个ImmutableList<整数>.然后它使用 Iterables 类来安全地获取特定索引处的值并在以下情况下提供默认值该索引不存在.这里我选择了 -1 表示无效指标值.

final ListtoTen = ImmutableList.copyOf(Ints.asList(ints));System.out.println(Iterables.get(toTen, 0, -1));System.out.println(Iterables.get(toTen, 100, -1));

如果由于某种原因你不能使用 Guava,你可以很容易地使用你自己的函数来做同样的事情.

私有静态T get(@Nonnull final Iterable<T> iterable, final int index, @Nonnull final T 缺失){if (index < 0) { return missing;}if (iterable instanceof List){最终名单<T>l = List.class.cast(iterable);返回 l.size() <= 索引 ?l.get(index) : 缺失;}别的{最终迭代器<T>迭代器 = iterable.iterator();for (int i = 0; iterator.hasNext(); i++){最后 T o = iterator.next();如果 (i == 索引) { 返回 o;}}返回失踪;}}

迭代时:

<块引用>

如果需要,这里是迭代原始 Array 的惯用方法知道索引和值:

这容易受到一次性错误的影响,这是主要原因java.lang.ArrayIndexOutOfBoundsException:

使用传统的 for/next 循环:

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 循环:

<块引用>

这里是迭代原始 Array 的惯用方法增强 for 循环 如果您不需要知道实际索引:

for (final int i : ints){System.out.format("%d", i);System.out.println();}

使用类型安全的迭代器:

<块引用>

这是使用增强的 对原始 Array 进行迭代的安全方法for 循环 并跟踪当前索引并避免出现遇到 java.lang.ArrayIndexOutOfBoundsException.

这使用 Guava 轻松地将 int[] 转换为 Iterable每个项目都应该包含它.

final Iteratorit = Ints.asList(ints).iterator();for (int i = 0; it.hasNext(); i++){System.out.format("index %d = %d", i, it.next());}

如果你不能使用 Guava 或者你的 int[] 很大,你可以像这样滚动你自己的 ImmutableIntArrayIterator:

 公共类 ImmutableIntArrayIterator 实现 Iterator{私人最终 int[] ba;私人 int currentIndex;public ImmutableIntArrayIterator(@Nonnull final int[] ba){this.ba = ba;如果(this.ba.length > 0){ this.currentIndex = 0;}否则 { currentIndex = -1;}}@覆盖public boolean hasNext() { return this.currentIndex >= 0 &&this.currentIndex + 1 

并使用与 Guava 相同的代码.

如果您绝对必须拥有项目的序号,那么以下是最安全的方法.

//假设 los 是一个字符串列表最终迭代器它 = los.iterator();for (int i = 0; it.hasNext(); i++){System.out.format("index %d = %s", i, it.next());}

此技术适用于所有 Iterables,它不是 index 本身,但它确实为您提供迭代中的当前位置,即使对于没有本机的事物<代码>索引.

最安全的方法:

<块引用>

最好的方法是始终使用 ImmutableLists/设置/Maps 来自 Guava as嗯:

final Listili = ImmutableList.copyOf(Ints.asList(ints));final Iteratoriit = ili.iterator();for (int i = 0; iit.hasNext(); i++){System.out.format("index %d = %d", i, iit.next());}

总结:

  1. 使用原始 Array 很难处理,在大多数情况下应该避免使用.它们有时容易受到细微的一次性错误的影响甚至回到 BASIC
  2. 的时代,困扰着新程序员
  3. 现代 Java 习惯用法使用正确的类型安全 Collections 并尽可能避免使用原始的 Array 结构.
  4. Immutable 类型现在几乎在所有情况下都是首选.
  5. Guava 是现代 Java 开发不可或缺的工具包.

If your question is I am getting a java.lang.ArrayIndexOutOfBoundsException in my code and I do not understand why it is happening. What does it mean and how can I avoid it?

This is meant to be the most comprehensive Canonical collection of information on this java.lang.ArrayIndexOutOfBoundsException topic as well as the java.lang.IndexOutOfBoundsException.

There are many questions like this and all of them have either vague no code answers, or mostly they are extremely specific and localized to the question at hand and do not address the root cause which is exactly the same in all cases.


If you see one that falls under this general case, rather than answer it with more duplicate specialized content, mark it as a duplicate of this one.

解决方案

What is java.lang.ArrayIndexOutOfBoundsException / java.lang.IndexOutOfBoundsException?

The JavaDoc curtly states:

Thrown to indicate that an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array.

What causes it to happen?

This exception means that you have tried to access an index in an array or array backed list and that index does not exist.

Java uses 0 based indexes. That means all indexes start with 0 as the index of the first element if it contains any elements.

The IndexOutOfBoundsException message is very explicit, it usually takes the form of:

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1

Where Index is the index that you requested that does not exist and Size is the length of the structure you were indexing into.

As you can see a Size: 1 means the only valid index is 0 and you were asking for what was at index 1.

For example if you have an raw Array of objects or primitive types the valid indexes are 0 to .length - 1, in the following example the valid indexes would be 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

This also applies to ArrayList as well as any other Collection classes that may be backed by an Array and allow direct access to the the index.

How to avoid the java.lang.ArrayIndexOutOfBoundsException / java.lang.IndexOutOfBoundsException?

When accessing directly by index:

This uses Guava to convert the raw primitive int[] array to an ImmutableList<Integer>. Then it uses the Iterables class to safely get the value at a particular index and provides a default value when that index does not exist. Here I chose -1 to indicate an invalid index value.

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));

If you can't use Guava for some reason it is easy to roll your own function to do this same thing.

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

When iterating:

Here is the idiomatic ways to iterate over a raw Array if you need to know the index and the value:

This is susceptible to one off errors which are the primary causes of an java.lang.ArrayIndexOutOfBoundsException:

Using a traditional 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]);  
}

Using an enhanced for/each loop:

Here is the idiomatic way to iterate over a raw Array with the enhanced for loop if you do not need to know the actual index:

for (final int i : ints)
{
    System.out.format("%d", i);
    System.out.println();
}

Using a type safe Iterator:

Here is the safe way to iterate over a raw Array with the enhanced for loop and track the current index and avoids the possibility of encountering an java.lang.ArrayIndexOutOfBoundsException.

This uses Guava to easily convert the int[] to something Iterable every project should include it.

final Iterator<Integer> it = Ints.asList(ints).iterator();
for (int i = 0; it.hasNext(); i++)
{
    System.out.format("index %d = %d", i, it.next());
}

If you can not use Guava or your int[] is huge you can roll your own ImmutableIntArrayIterator as such:

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(); }
}

And use the same code as you would with Guava.

If you absolutely must have the ordinal of the item the following is the safest way to do it.

// 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());
}

This technique works for all Iterables, it is not an index perse but it does give you the current position in the iteration even for things that do not have a native index.

The safest way:

The best way is to always use ImmutableLists/Set/Maps from Guava as well:

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:

  1. Using raw Array are difficult to work with and should be avoided in most cases. They are susceptible to sometimes subtle one off errors which have plague new programmers even back to the days of BASIC
  2. Modern Java idioms use proper type safe Collections and avoid using raw Array structures if at all possible.
  3. Immutable types are preferred in almost all cases now.
  4. Guava is an indispensable toolkit for modern Java development.

这篇关于如何避免 ArrayIndexOutOfBoundsException 或 IndexOutOfBoundsException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆