2011-09-15 63 views
1

下面的代码:这段代码为什么会抛出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) 

这是为什么?

回答

2

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

为了解决这个问题,可以考虑存储一个记录下一个自由索引的计数器,或者使用一些简单的数学来推导卡片应该从其花色和价值中获得的位置。例如,因为在外循环的每次迭代中,您将写入ranks.length元素到数组中,在迭代中(i,n),您将写入数组索引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,它包装一个数组并为您进行跟踪。

希望这会有所帮助!

+0

或使用'ArrayList ' – Falmarri

2
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构造函数中的行列/套装专柜 - 也修正了这个问题。

0

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

+1

这不是问题,但它会是下一个! – shanethehat

+0

这仍然不能解决他的问题......;) –

0

在改名的变量考虑它:

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] 

编码愉快。

+2

这不是问题,但它会是下一个问题! – shanethehat

+1

虽然我们正在谈论更好的编码实践:使用和新卡[suits.length * cards.length] ... for(String S:suits)... for(String C:cards)... – ddyer

相关问题