繁体   English   中英

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

[英]Why does this code throw an ArrayIndexOutOfBoundsException?

这是代码:

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

正如您所看到的,这会循环通过两个给定的数组并为每个组合生成一张卡片。 共有13个排名×4个套装= 52张牌。 我预计在第52次迭代中, cards.length将是51,但编译器说

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

这是为什么?

cards[cards.length]

因为您正在尝试使用不存在的索引。 cards.length是52,你的数组是0 - 51。

怀疑你试图将每张卡插入该阵列,这意味着你需要另一个计数器;)

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

编辑:我没有抓到的是其他人提到的 - 你也有在Card构造函数中切换的排名/套装的计数器 - 修正了。

问题是cards.length不是数组中使用的元素总数; 它是数组中元素总数 ,无论你到目前为止存储在数组中的是什么。 因此,只要执行内部循环,这将尝试访问数组的第52个元素,从而导致您看到的异常。

要解决此问题,请考虑存储一个计数器,该计数器将跟踪下一个自由索引,或者使用一些简单的数学运算来得出卡应该从其套装和值中进入的位置。 例如,因为在外部循环的每次迭代中,您将把ranks.length元素写入数组,在迭代( in )上,您将写入数组索引i * ranks.length + n 使用它,你可以将内循环重写为

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

另外,请注意您对阵列的访问是错误的。 现在,你正在写作

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

但是, i范围超过西装,而不是价值。 正确的代码将是

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

这给出了最终的实现:

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

但更一般地说,不要使用数组的.length字段来跟踪有多少使用过的元素。 你需要单独存储它。 或者,考虑使用ArrayList ,它包装数组并为您跟踪。

希望这可以帮助!

排名等级和套装的索引变量被交换。 (不要用手掌损坏头部。)

考虑使用重命名的变量:

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

使用in并不总是最好的。 (我会使用sr 。)

另外,考虑一下:

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

快乐的编码。

暂无
暂无

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

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