簡體   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