web-dev-qa-db-fra.com

Qu'est-ce qu'une exception NumberFormatException et comment puis-je résoudre ce problème?

Error Message:
Exception in thread "main" Java.lang.NumberFormatException: For input string: "Ace of Clubs"
    at Java.lang.NumberFormatException.forInputString(NumberFormatException.Java:65)
    at Java.lang.Integer.parseInt(Integer.Java:580)
    at Java.lang.Integer.parseInt(Integer.Java:615)
    at set07102.Cards.main(Cards.Java:68)
C:\Users\qasim\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)

Ma boucle While:

while (response != 'q' && index < 52) {
    System.out.println(cards[index]);
    int first_value = Integer.parseInt(cards[index]);
    int value = 0;
    //Add a Scanner
    Scanner scanner = new Scanner(System.in);
    System.out.println("Will the next card be higher or lower?, press q if you want to quit");
    String guess = scanner.nextLine();
    if(cards[index].startsWith("Ace")) { value = 1; }
    if(cards[index].startsWith("2")) { value = 2; }
    if(cards[index].startsWith("3")) { value = 3; }
    //checking 4-10
    if(cards[index].startsWith("Queen")){ value = 11; }
    if(cards[index].startsWith("King")){ value = 12; }
    if(guess.startsWith("h")){
        if(value > first_value){ System.out.println("You answer was right, weldone!"); } 
        else { System.out.println("You answer was wrong, try again!"); }
    } else if(guess.startsWith("l")){
        if(value < first_value) { System.out.println("You answer as right, try again!"); }
        else { System.out.println("You answer was wrong, try again!"); }
    } else { System.out.println("Your was not valid, try again!"); }
    scanner.close();            
    index++;
}//end of while loop
17
Qasim Imtiaz
Error Message:
Exception in thread "main" Java.lang.NumberFormatException: For input string: "Ace of Clubs"
    at Java.lang.NumberFormatException.forInputString(NumberFormatException.Java:65)
    at Java.lang.Integer.parseInt(Integer.Java:580)
    at Java.lang.Integer.parseInt(Integer.Java:615)
    at set07102.Cards.main(Cards.Java:68)
C:\Users\qasim\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1

veux dire:

There was an error. We try to give you as much information as possible
It was an Exception in main thread. It's called NumberFormatException and has occurred for input "Ace of Clubs".
at line 65th of NumberFormatException.Java which is a constructor,
which was invoked from Integer.parseInt() which is in file Integer.Java in line 580,
which was invoked from Integer.parseInt() which is in file Integer.Java in line 615,
which was invoked from method main in file Cards.Java in line 68.

It has resulted in exit code 1

En d'autres termes, vous avez essayé d'analyser "Ace of Clubs" en une int ce que Java ne peut pas faire avec la méthode Integer.parseInt. Java a fourni un magnifique stacktrace qui vous dit exactement quel est le problème. L'outil que vous recherchez est debugger et utiliser points d'arrêt vous permettra d'inspecter l'état état de votre application au moment choisi.

La solution pourrait être la logique suivante si vous souhaitez utiliser analyse} _:

if (cards[index].startsWith("Ace")) 
    value = 1;
else if (cards[index].startsWith("King"))
    value = 12;
else if (cards[index].startsWith("Queen"))
    value = 11;
...
else {
    try {
        Integer.parseInt(string.substring(0, cards[index].indexOf(" "))); 
    } catch (NumberFormatException e){
        //something went wrong
    }
}

Qu'est-ce qu'une Exception en Java?

Une exception est un événement qui se produit lors de l'exécution d'un programme, qui perturbe le flux normal des instructions du programme.

- Documentation

Constructeurs et utilisation dans Integer#parseInt

static NumberFormatException forInputString(String s) {
    return new NumberFormatException("For input string: \"" + s + "\"");
}

public NumberFormatException (String s) {
    super (s);
}

Ils sont importants pour comprendre comment lire le stacktrace. Regardez comment la NumberFormatException est levée de Integer#parseInt:

if (s == null) {
    throw new NumberFormatException("null");
}

ou plus tard si le format de l'entrée String s n'est pas analysable:

throw NumberFormatException.forInputString(s); 

Qu'est-ce qu'une NumberFormatException?

Lancé pour indiquer que l'application a tenté de convertir une chaîne en un des types numériques, mais que la chaîne n'a pas le format approprié.

- Documentation

NumberFormatExceptionextendsIllegalArgumentException. Cela nous dit que c'est plus spécialisé IllegalArgumentException. En effet, il est utilisé pour souligner que même si le type d'argument était correct (String), le contenu de String n'était pas numérique (a, b, c, d, e, f sont considérés comme des chiffres dans HEX et sont légaux quand nécessaire).

Comment je le répare?
Bien, ne corrige pas le fait qu'il soit lancé. C'est bien que ça soit jeté. Vous devez prendre en compte certaines choses:

  1. Puis-je lire le stacktrace?
  2. La String qui provoque une Exception est-elle une null?
  3. Cela ressemble-t-il à un chiffre?
  4. Est-ce "ma chaîne" ou l'entrée de l'utilisateur?
  5. à suivre

Un d. 1.

La première ligne d'un message contient des informations selon lesquelles l'exception s'est produite et l'entrée String à l'origine du problème. La chaîne suit toujours : et est citée ("some text"). Ensuite, vous vous intéressez à lire le stacktrace à partir de la fin, car les premières lignes sont généralement le constructeur, la méthode d’analyse etc. de NumberFormatException, puis à la fin, il ya votre méthode dans laquelle vous avez créé un bogue. Il sera indiqué dans quel fichier il a été appelé et dans quelle méthode. Même une ligne sera attachée. Tu verras. L'exemple de comment lire le stacktrace est ci-dessus.

Un d. 2.

Lorsque vous voyez qu'au lieu de "For input string:" et de l'entrée, il existe une null (pas "null"), cela signifie que vous avez essayé de passer la référence null à un nombre. Si vous voulez réellement traiter comme 0 ou tout autre nombre, vous pourriez être intéressé par mon autre article sur StackOverflow. Il est disponible ici .

La description de la résolution de nulls inattendue est bien décrite sur le thread StackOverflow Qu'est-ce qu'une exception NullPointerException et comment puis-je résoudre ce problème?

Un d. 3.

Si la String qui suit le : et qui est entre guillemets ressemble à un chiffre, il se peut qu'il y ait un caractère que votre système ne décode pas ou un espace blanc invisible. De toute évidence, " 6" ne peut pas être analysé aussi bien que "123 " ne le peut pas. C'est à cause des espaces. Mais il peut arriver que la String ressemble à "6" mais en réalité, sa longueur sera plus grande que le nombre de chiffres que vous pouvez voir.

Dans ce cas, je suggère d'utiliser le debugger ou au moins System.out.println et d'imprimer la longueur de la String que vous essayez d'analyser. S'il indique plus que le nombre de chiffres, essayez de passer stringToParse.trim() à la méthode d'analyse. Si cela ne fonctionne pas, copiez la chaîne entière après le : et décodez-la à l'aide du décodeur en ligne. Cela vous donnera les codes de tous les caractères.

Il y a aussi un cas que j'ai trouvé récemment dans StackOverflow, que vous pourriez voir, où l'entrée ressemble à un nombre, par exemple. "1.86" et il ne contient que ces 4 caractères mais l'erreur existe toujours. Rappelez-vous, on ne peut analyser que des entiers avec # Integer # parseInt #. Pour analyser les nombres décimaux, utilisez Double#parseDouble.

Une autre situation est, lorsque le numéro comporte plusieurs chiffres. Peut-être est-il trop grand ou trop petit pour s'adapter à int ou long. Vous voudrez peut-être essayer new BigDecimal(<str>).

Un d. 4.

Nous arrivons enfin à l’endroit dans lequel nous sommes d’accord, à savoir que nous ne pouvons éviter les situations où l’utilisateur tape "abc" sous forme de chaîne numérique. Pourquoi? Parce qu'il peut. Heureusement, c'est parce qu'il est testeur ou simplement geek. Dans le mauvais cas, c'est l'attaquant.

Que puis-je faire maintenant? Eh bien, Java nous donne try-catch vous pouvez faire ce qui suit:

try {
    i = Integer.parseInt(myString);
} catch (NumberFormatException e) {
    e.printStackTrace();
    //somehow workout the issue with an improper input. It's up to your business logic.
}
36
xenteros

Qu'est-ce qu'une NumberFormatException?

Cette exception est levée pour indiquer que l'application a a tenté de convertir une string en l’un des types numériques, mais que la string n'a pas le format approprié.

Dans votre cas, selon votre trace de pile, cette exception a été générée par Integer.parseInt(String) , ce qui signifie que la variable String fournie ne contient pas de variable analysable integer. Et toujours selon la trace de la pile, cela est dû au fait que vous avez essayé d'analyser la String "Ace of Clubs" comme un entier qui ne peut pas fonctionner car ce n'est pas la représentation String d'un entier.

Comment le réparer?

La méthode la plus simple et la plus générique consiste à intercepter l'exception NumberFormatException

int value = -1;
try {
    value = Integer.parseInt(myString);
} catch (NumberFormatException e) {
    // The format was incorrect
}

Cela fonctionnera, mais la capture d'une exception est lente car il faut créer la pile d'appels pour créer la variable Exception qui est coûteuse. Si vous pouvez l'éviter, faites-le. De plus, vous devrez gérer l’exception correctement, ce qui n’est pas toujours évident.

Vous pouvez également utiliser un regular expression pour vérifier d’abord si Stringmatches avec un Integer, mais il est sujet à des erreurs car vous pourriez facilement utiliser un regular expression incorrect.


Dans votre cas, une approche plus OO devrait être utilisée au lieu de traiter String, par exemple, vous pouvez utiliser un class ou un enum pour représenter vos cartes au lieu d'utiliser un simple String car il est beaucoup plus sujet aux erreurs déjà remarqué. 

Donc, si vous décidez d'utiliser une classe dédiée pour votre carte, votre code pourrait être:

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;
    }
}

Pour la couleur et le rang d'une carte, nous pouvons utiliser un enum car il y a un nombre limité de rangs et de couleurs.

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
}

Alors cards serait un tableau de Card au lieu d'un tableau de String, et pourrait être initialisé comme suit:

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]);
    }
}

Si vous devez mélanger votre tableau de cartes, vous pouvez procéder comme suit (veuillez noter que si vous décidez d'utiliser une List de cartes au lieu d'un tableau, utilisez simplement Collections.shuffle(list))

List<Card> allCards = Arrays.asList(cards);
Collections.shuffle(allCards);
allCards.toArray(cards);

Vous pourrez alors accéder directement à la valeur de votre carte avec cards[index].getRank().getValue() sans prendre le risque d'obtenir une exception (sauf une IndexOutOfBoundsException si vous n'utilisez pas un index approprié).

9
Nicolas Filotto

Il semble que cards[] soit String array et que vous essayez de convertir Ace of Clubs en Integer .

int first_value = Integer.parseInt(cards[index]);
6
Vivek G
Java.lang.NumberFormatException 

se produit lorsque vous essayez d'analyser une entrée qui n'est pas une chaîne numérique.

Dans votre cas, vous essayez d’analyser une chaîne (qui n’a pas de numéro) comme Integer . Comme il n’est pas possible.

int first_value = Integer.parseInt(cards[index]);//cards[index] value should be //number string "123" not "abc"
2
Rajesh Gopu

Une exception NumberFormatException est la manière dont Java doit vous dire "J'ai essayé de convertir une chaîne en int et je ne pouvais pas le faire".

Dans votre trace d'exception, vous pouvez lire

Exception in thread "main" Java.lang.NumberFormatException: For input string: "Ace of Clubs"
    at Java.lang.NumberFormatException.forInputString(NumberFormatException.Java:65)
    at Java.lang.Integer.parseInt(Integer.Java:580)
    at Java.lang.Integer.parseInt(Integer.Java:615)
    at set07102.Cards.main(Cards.Java:68)

En gros, cela signifie qu'à la ligne 68 de votre code, vous appelez la méthode Integer.parseInt en transmettant "Ace of Clubs" comme paramètre. Cette méthode attend une valeur entière représentée sous forme de chaîne, par exemple. "4", la méthode se plaint donc d'avoir lancé une exception NumberFormatException car "Ace of Clubs" ne semble pas du tout un entier.

2
jmlotero

La toute première chose qui m'a jeté pour une boucle (sans jeu de mots) était que vous limitiez la valeur à 1-13 alors qu'elle doit être 0-52. Aussi, avec votre logique, la valeur a toujours été supérieure. Une meilleure approche consiste à utiliser un générateur de nombres. Voici mon code utilisant un générateur de nombres (ou Java Random):

public static void main(String[] args) {

String[] cards = { "Ace of Clubs", "1 of Clubs", "2 of Clubs",
        "3 of Clubs", "4 of Clubs", "5 of Clubs", "6 of Clubs",
        "7 of Clubs", "8 of Clubs", "9 of Clubs", "10 of Clubs",
        "Queen of Clubs", "King of Clubs", "Ace of Diamonds",
        "1 of Diamonds", "2 of Diamonds", "3 of Diamonds",
        "4 of Diamonds", "5 of Diamonds", "6 of Diamonds",
        "7 of Diamonds", "8 of Diamonds", "9 of Diamonds",
        "10 of Diamonds", "Queen of Diamonds", "King of Diamonds",
        "Ace of Hearts", "1 of Hearts", "2 of Hearts", "3 of Hearts",
        "4 of Hearts", "5 of Hearts", "6 of Hearts", "7 of Hearts",
        "8 of Hearts", "9 of Hearts", "10 of Hearts",
        "Queen of Hearts", "King of Hearts", "Ace of Spades",
        "1 of Spades", "2 of Spades", "3 of Spades", "4 of Spades",
        "5 of Spades", "6 of Spades", "7 of Spades", "8 of Spades",
        "9 of Spades", "10 of Spades", "Queen of Spades",
        "King of Spades" };

Scanner scanner = new Scanner(System.in);
Random Rand = new Random();
String response = "";
int index = 0;
int value = 0;  
while (!response.equals("q") && index < 52) {

    // set next card value based on current set of cards in play
    if (cards[index].endsWith("Clubs")) {
        value = Rand.nextInt(12);
    }
    if (cards[index].endsWith("Diamonds")) {
        value = Rand.nextInt(12) + 13;
    }
    if (cards[index].endsWith("Hearts")) {
        value = Rand.nextInt(12) + 26;
    }
    if (cards[index].endsWith("Spades")) {
        value = Rand.nextInt(12) + 39;
    }

    // display card too user (NOTE: we use the random number not the index)
    System.out.println("Card is: " + cards[value]);

    // ask user what well the next card be
    System.out.println("Will the next card be higher or lower?, press q if you want to quit");
    response = scanner.nextLine();

    // display if user was right (NOTE: compared the random number to the current index)
    // ignore incorrect response and just continue
    if ((value > index && response.startsWith("h")) || (value < index && response.startsWith("l"))) {
        System.out.println("You answer was right, well done!");
    } else {
        System.out.println("You answer was wrong, try again!");
    }

    // continue loop
    index++;
}
}

En ce qui concerne l’exception NumberFormatException, Nicolas Filotto s’est bien débrouillé pour expliquer cela.

1
thekodester

Un NumberFormatException signifie que Integer.parseInt() ne pouvait pas traduire la chaîne en un nombre.

Je suggérerais une des deux options:

  1. Encapsulez les cartes en tant que combo nom (chaîne)/valeur (int). Utilisez la valeur pour faire des comparaisons et le nom pour présenter les informations à l'utilisateur. Cards[] devient alors une liste de cartes, pas de chaînes.

  2. Analyser les chaînes vous-même. Ce qui peut être plus facile, puisque vous l'avez déjà fait avec les bits if(cards[index].startsWith("Ace")) { value = 1; }. Vous pouvez les déplacer dans une fonction appelée CardToInt() (ou autre) et utiliser cette fonction à la place de Integer.parseInt().

1
Andrew Tofelt
int first_value = Integer.parseInt(cards[index]); 

en écrivant la déclaration ci-dessus, vous essayez d'analyser "Ace of Clubs" comme un nombre. 

vous pouvez utiliser la méthode suivante pour tester si une chaîne peut être analysée en tant qu'Integer:

boolean tryParseInt(String value) {  
     try {  
         Integer.parseInt(value);  
         return true;  
      } catch (NumberFormatException e) {  
         return false;  
      }  
}

En ce qui concerne votre question, qu’est-ce que NumberFormatException: Indique que l’application a tenté de convertir une chaîne en l’un des types numériques, mais que la chaîne n’a pas le format approprié. (ref - http://docs.Oracle.com/javase/7/docs/api/Java/lang/NumberFormatException.html )

1
roopaliv

L'exception vient dans votre code, où vous convertissez la chaîne en un entier:

int first_value = Integer.parseInt(cards[index]);

où vous passez une chaîne en tant que "Ace of Clubs" qu'il n'est pas possible de convertir en tant qu'entier, elle génère donc une exception de format de nombre. Vous pouvez utiliser,

try {
     ....
     // Your Code
     ....
    }
catch(NumberFormatException e)
{
    e.getMessage();  //You can use anyone like printStackTrace() ,getMessage() to handle the Exception
}
0
Anands23