简体   繁体   English

为什么这段代码抛出一个ArrayIndexOutOfBoundsException?

[英]Why does this code throw an ArrayIndexOutOfBoundsException?

Here's the code: 这是代码:

public class Deck {

    private Card[] cards;

    public Deck() {
        cards = new Card[52];
        String[] ranks = {"ace","two","three","four","five","six","seven","eight","nine","ten","jack","queen","king"};
        String[] suits = {"hearts","diamonds","clubs","spades"};
        for(int i = 0; i < suits.length; i++) {
            for(int n = 0; n < ranks.length; n++) {
                cards[cards.length] = new Card(ranks[i],suits[n]);
            }
        }
    }
}

As you can see, this loops though the two given arrays and generates a card for every combination. 正如您所看到的,这会循环通过两个给定的数组并为每个组合生成一张卡片。 There are 13 ranks x 4 suits = 52 cards. 共有13个排名×4个套装= 52张牌。 I expected that on the 52nd iteration, cards.length would be 51, but the compiler says 我预计在第52次迭代中, cards.length将是51,但编译器说

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 52
    at com.cards.Deck.<init>(Deck.java:14)

Why is that? 这是为什么?

cards[cards.length]

Because you're trying to use an index that doesn't exist. 因为您正在尝试使用不存在的索引。 cards.length is 52, your array is 0 - 51. cards.length是52,你的数组是0 - 51。

I suspect you're trying to insert each card into that array, which means you need another counter ;) 怀疑你试图将每张卡插入该阵列,这意味着你需要另一个计数器;)

int cardIndex = 0;
for(int i = 0; i < suits.length; i++) {
    for(int n = 0; n < ranks.length; n++, cardIndex++) {
        cards[cardIndex] = new Card(ranks[n],suits[i]);
    }
}

EDIT: What I didn't catch is what others have mentioned - you also have the counters for ranks/suits switched in the Card constructor - fixed that too. 编辑:我没有抓到的是其他人提到的 - 你也有在Card构造函数中切换的排名/套装的计数器 - 修正了。

The issue is that cards.length is not the total number of elements used in the array; 问题是cards.length不是数组中使用的元素总数; it's the total number of elements in the array, regardless of what you've stored in the array so far. 它是数组中元素总数 ,无论你到目前为止存储在数组中的是什么。 Consequently, as soon as you execute the inner loop, this will try accessing the 52nd element of the array, causing the exception you've seen. 因此,只要执行内部循环,这将尝试访问数组的第52个元素,从而导致您看到的异常。

To fix this, consider instead storing a counter that will keep track of the next free index, or use some simple math to derive the position that the card should go in from its suit and value. 要解决此问题,请考虑存储一个计数器,该计数器将跟踪下一个自由索引,或者使用一些简单的数学运算来得出卡应该从其套装和值中进入的位置。 For example, since on each iteration of the outer loop you will write ranks.length elements to the array, on iteration ( i , n ) you will write to array index i * ranks.length + n . 例如,因为在外部循环的每次迭代中,您将把ranks.length元素写入数组,在迭代( in )上,您将写入数组索引i * ranks.length + n Using this, you could rewrite the inner loop as 使用它,你可以将内循环重写为

    // Careful... still buggy!
    for(int i = 0; i < suits.length; i++) {
        for(int n = 0; n < ranks.length; n++) {
            cards[i * ranks.length + n] = new Card(ranks[i],suits[n]);
        }
    }

Additionally, note that your access into the arrays is wrong. 另外,请注意您对阵列的访问是错误的。 Right now, you're writing 现在,你正在写作

new Card(ranks[i],suits[n]);

However, i ranges over suits, not values. 但是, i范围超过西装,而不是价值。 The proper code would be 正确的代码将是

new Card(ranks[n],suits[i]);

Which gives this final implementation: 这给出了最终的实现:

    for(int i = 0; i < suits.length; i++) {
        for(int n = 0; n < ranks.length; n++) {
            cards[i * ranks.length + n] = new Card(ranks[n],suits[i]);
        }
    }

More generally, though, don't use the .length field of an array to track how many used elements there are. 但更一般地说,不要使用数组的.length字段来跟踪有多少使用过的元素。 You'll need to store that separately. 你需要单独存储它。 Alternatively, consider using an ArrayList , which wraps an array and tracks this for you. 或者,考虑使用ArrayList ,它包装数组并为您跟踪。

Hope this helps! 希望这可以帮助!

The index variables for ranks ranks and suits are exchanged. 排名等级和套装的索引变量被交换。 (Don't damage your head with your palm.) (不要用手掌损坏头部。)

Consider it with renamed variables: 考虑使用重命名的变量:

for(int SUIT = 0; SUIT < suits.length; SUIT++) {
    for(int RANK = 0; RANK < ranks.length; RANK++) {
        cards[cards.length] = new Card(ranks[SUIT],suits[RANK]);
    }
}

It isn't always best to use i and n . 使用in并不总是最好的。 (I would have used s and r .) (我会使用sr 。)

Also, consider: 另外,考虑一下:

Card[] cards = new Card[X];
cards[X] // will never be "in bounds", indices from [0, X-1]

Happy coding. 快乐的编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM