代码如下:
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 个等级 x 4 个花色 = 52 张牌。我预计在第 52 次迭代时,cards.length
将是 51,但编译器说
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 52
at com.cards.Deck.<init>(Deck.java:14)
这是为什么?
最佳答案
问题是 cards.length
不是数组中使用的元素总数;它是数组中的元素总数,不管到目前为止您在数组中存储了什么。因此,一旦您执行内部循环,这将尝试访问数组的第 52 个元素,从而导致您看到的异常。
要解决此问题,请考虑改为存储一个计数器来跟踪下一个空闲索引,或者使用一些简单的数学运算从其花色和值(value)中推导出牌应该进入的位置。例如,由于在外循环的每次迭代中,您都会将 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
,它包装一个数组并为您跟踪它。
希望这对您有所帮助!
关于java - 为什么此代码会抛出 ArrayIndexOutOfBoundsException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7424413/