Error Message:
Exception in thread \"main\" java.lang.NumberFormatException: For input string: \"Ace of Clubs\"
at java.lang.NumberFormatException.forInputString
NumberFormatException
?This exception is thrown to indicate that the application has attempted to convert a
string
to one of the numeric types, but that thestring
does not have the appropriate format.
In your case, according to your stack trace this exception was thrown by Integer.parseInt(String) which means that the provided String
does not contain a parseable integer
. And still according to the stack trace, it is due to the fact that you tried to parse the String
"Ace of Clubs" as an integer which cannot work as it is not the String
representation of an integer.
The simplest and generic way is to catch the exception NumberFormatException
int value = -1;
try {
value = Integer.parseInt(myString);
} catch (NumberFormatException e) {
// The format was incorrect
}
It will work but catching an exception is slow because it needs to build the call stack to create the Exception
which is costly, so if you can avoid it do it. Moreover you will need to manage the exception properly which is not always obvious.
Or you could use a regular expression
to check first if the String
matches with an Integer
but it is quite error prone as you could easily use a wrong regular expression
.
In your case, a more OO approach should be used instead of dealing with String
, for example you could use a class
or an enum
to represent your cards instead of using simple String
because it is much more error prone as you have already noticed.
So if you decide to use a dedicated class for your card, your code could be:
public class Card {
private final Rank rank;
private final Suit suit;
public Card(final Rank rank, final Suit suit) {
this.rank = rank;
this.suit = suit;
}
public Rank getRank() {
return this.rank;
}
public Suit getSuit() {
return this.suit;
}
}
For the suit and the rank of a card, we can use an enum
since there are limited amounts of existing ranks and suits.
public enum Rank {
ACE(1), TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), HEIGHT(8),
NINE(9), TEN(10), JACK(11), QUEEN(12), KING(13);
private final int value;
Rank(final int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
public enum Suit {
SPADE, HEART, DIAMOND, CLUB
}
Then cards
would be an array of Card
instead of an array of String
, and could be initialized as next:
Rank[] ranks = Rank.values();
Suit[] suits = Suit.values();
Card[] cards = new Card[ranks.length * suits.length];
for (int i = 0; i < ranks.length; i++) {
for (int j = 0; j < suits.length; j++) {
cards[i * suits.length + j] = new Card(ranks[i], suits[j]);
}
}
If you need to shuffle your array of cards, you can proceed as next (please note that if you decide to use a List
of cards instead of an array simply use Collections.shuffle(list)
)
List allCards = Arrays.asList(cards);
Collections.shuffle(allCards);
allCards.toArray(cards);
Then you will be able to access directly to the value of your card with cards[index].getRank().getValue()
without taking the risk to get an exception (except an IndexOutOfBoundsException
if you don't use a proper index).