What is a NumberFormatException and how can I fix it?

前端 未结 9 1354
渐次进展
渐次进展 2020-11-21 04:25
Error Message:
Exception in thread \"main\" java.lang.NumberFormatException: For input string: \"Ace of Clubs\"
    at java.lang.NumberFormatException.forInputString         


        
9条回答
  •  清酒与你
    2020-11-21 04:51

    What is a NumberFormatException?

    This exception is thrown to indicate that the application has attempted to convert a string to one of the numeric types, but that the string 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.

    How to fix it?

    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).

提交回复
热议问题