O que é um NumberFormatException e como posso corrigi-lo?

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) 

Meu While Loop:

 while (response != 'q' && index  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 

 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 

significa:

 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 

Em outras palavras, você tentou analisar "Ace of Clubs" para um int que Java não pode fazer com o método Integer.parseInt . Java forneceu um stacktrace bonito que informa exatamente qual é o problema. A ferramenta que você está procurando é o depurador e usar pontos de interrupção permitirá que você inspecione o estado de sua aplicação no momento escolhido.

A solução pode ser a lógica a seguir, caso você queira usar a análise :

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

O que é uma Exception em Java?

Uma exceção é um evento, que ocorre durante a execução de um programa, que interrompe o stream normal das instruções do programa.

– Documentação

Construtores e uso em Integer#parseInt

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

Eles são importantes para entender como ler o stacktrace. Veja como o NumberFormatException é lançado do Integer#parseInt :

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

ou mais tarde, se o formato da String s input String s não for analisável:

 throw NumberFormatException.forInputString(s); 

O que é um NumberFormatException ?

Lançada para indicar que o aplicativo tentou converter uma string em um dos tipos numéricos, mas que a string não possui o formato apropriado.

– Documentação

NumberFormatException extends IllegalArgumentException . Diz-nos que é mais IllegalArgumentException especializado. Na verdade, é usado para destacar que, embora o tipo de argumento esteja correto ( String ), o conteúdo da String não era numérico ( a, b, c, d, e, f são considerados dígitos em HEX e são válidos quando necessário ).

Como faço para corrigir isso?
Bem, não conserte o fato de que é jogado. É bom que seja jogado. Há algumas coisas que você precisa considerar:

  1. Posso ler o stacktrace?
  2. A String que causa uma Exception é null ?
  3. Parece um número?
  4. É ‘minha string’ ou input do usuário?
  5. continua

De Anúncios. 1

A primeira linha de uma mensagem é uma informação que a Exceção ocorreu e a String input que causou o problema. A String sempre segue : e é citada ( "some text" ). Então você se interessa em ler o stacktrace do final, já que as primeiras linhas são normalmente o construtor, o método de análise de NumberFormatException , etc. Então, no final, há o seu método no qual você criou um bug. Será indicado em qual arquivo foi chamado e em qual método. Até uma linha será anexada. Você verá. O exemplo de como ler o stacktrace está acima.

De Anúncios. 2

Quando você vê, que em vez de "For input string:" e a input, há um null ( não "null" ) significa que você tentou passar a referência nula para um número. Se você realmente quer tratar é como 0 ou qualquer outro número, você pode estar interessado no meu outro post no StackOverflow. Está disponível aqui .

A descrição da resolução de null inesperados é bem descrita no thread do StackOverflow O que é um NullPointerException e como posso corrigi-lo? .

De Anúncios. 3

Se o String que segue o : e for citado se parecer com um número em sua opinião, pode haver um caractere que seu sistema não decodifica ou um espaço em branco invisível. Obviamente, " 6" não pode ser analisado, assim como "123 " não pode ser analisado. É por causa dos espaços. Mas pode acontecer que a String pareça "6" mas na verdade o comprimento será maior que o número de dígitos que você pode ver.

Neste caso, sugiro usar o depurador ou pelo menos System.out.println e imprimir o comprimento da String você está tentando analisar. Se ele mostrar mais do que o número de dígitos, tente passar stringToParse.trim() para o método de análise. Se não funcionar, copie toda a string após o : e decodifique-a usando o decodificador online. Isso lhe dará códigos de todos os personagens.

Há também um caso que eu encontrei recentemente no StackOverflow , que você pode ver, que a input se parece com um número, por exemplo, "1.86" e contém apenas esses 4 caracteres, mas o erro ainda existe. Lembre-se, só é possível analisar inteiros com # Integer # parseInt #. Para analisar números decimais, deve-se usar Double#parseDouble .

Outra situação é quando o número tem muitos dígitos. Pode ser, que é muito grande ou muito pequeno para caber dentro ou por long . Você pode querer experimentar o new BigDecimal() .

De Anúncios. 4

Finalmente chegamos ao local em que concordamos, que não podemos evitar situações em que o usuário digita “abc” como uma string numérica. Por quê? Porque ele pode. Em um caso de sorte, é porque ele é um testador ou simplesmente um geek. Em um caso ruim, é o atacante.

O que eu posso fazer agora? Bem, Java nos dá try-catch você pode fazer o seguinte:

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

O que é um NumberFormatException ?

Essa exceção é lançada para indicar que o aplicativo tentou converter uma string em um dos tipos numéricos, mas que a string não possui o formato apropriado.

No seu caso, de acordo com seu rastreamento de pilha, essa exceção foi lançada por Integer.parseInt(String) que significa que a String fornecida não contém um integer analisável. E ainda de acordo com o rastreamento de pilha, é devido ao fato de que você tentou analisar a StringAce of Clubs ” como um inteiro que não pode funcionar, pois não é a representação de String de um inteiro.

Como corrigi-lo?

A maneira mais simples e genérica é pegar a exceção NumberFormatException

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

Ele funcionará, mas a captura de uma exceção é lenta porque ela precisa construir a pilha de chamadas para criar a Exception que é cara, portanto, se você puder evitar, faça isso. Além disso, você precisará gerenciar a exceção corretamente, o que nem sempre é óbvio.

Ou você pode usar uma regular expression para verificar primeiro se a String matches a um Integer mas ela é bastante propensa a erros, já que você poderia facilmente usar uma regular expression errada.


No seu caso, uma abordagem OO mais deve ser usada em vez de lidar com String , por exemplo, você poderia usar uma class ou um enum para representar seus cartões em vez de usar String simples, porque é muito mais propenso a erros, como você já notou.

Então, se você decidir usar uma class dedicada para o seu cartão, seu código pode ser:

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

Para o naipe e a sorting de um cartão, podemos usar um enum pois há quantidades limitadas de classificações e ações existentes.

 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 } 

Em seguida, os cards seriam uma matriz de Card vez de uma matriz de String e poderiam ser inicializados como próximo:

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

Se você precisar embaralhar sua matriz de cartas, você pode proceder como se segue (por favor, note que se você decidir usar uma List de cartas em vez de uma matriz, simplesmente use Collections.shuffle(list) )

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

Então você poderá acessar diretamente o valor do seu cartão com cards[index].getRank().getValue() sem correr o risco de obter uma exceção (exceto um IndexOutOfBoundsException se você não usar um índice apropriado).

Parece que cards[] é array de String e você está tentando converter Ace of Clubs em Integer .

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

ocorre quando você está tentando analisar alguma input que não seja uma string Number.

No seu caso, você está tentando analisar uma string (que não tem número) como Integer. Como não é possível exceção NumberFormatException ocorreu.

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

Um NumberFormatException é o jeito que o Java tem para dizer “Eu tentei converter um String para int e não consegui fazê-lo”.

Em seu rastreio de exceção, você pode ler

 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) 

Basicamente, isso significa que na linha 68 do seu código você chama o método Integer.parseInt passando “Ace of Clubs” como paremeter. Este método espera um valor inteiro representado como String, por exemplo, “4”, então o método reclama jogando uma NumberFormatException porque “Ace of Clubs” não parece ser um inteiro.

A primeira coisa que me jogou por um loop (sem trocadilhos) foi que você estava limitando o valor a 1-13 quando precisa ser 0-52. Também com sua lógica o valor sempre foi maior. Uma abordagem melhor é com um gerador de números. Aqui está o meu código usando um gerador de números (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++; } } 

Quanto ao NumberFormatException, acredito que Nicolas Filotto fez um bom trabalho explicando isso.

Um NumberFormatException significa que Integer.parseInt() não pôde converter a string em um número.

Eu sugeriria uma das duas opções:

  1. Encapsule cartões como um combo de nome (string) / valor (int). Use o valor para fazer comparações e o nome para apresentar informações ao usuário. Cards[] então se torna uma lista de cards, não de strings.

  2. Analise as cordas você mesmo. O que pode ser mais fácil, já que você já fez isso com o if(cards[index].startsWith("Ace")) { value = 1; } if(cards[index].startsWith("Ace")) { value = 1; } bits. Você pode movê-los para uma function chamada CardToInt() (ou qualquer outro) e usar essa function em vez de Integer.parseInt() .

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

Ao escrever a declaração acima, você está tentando analisar “Ace of Clubs” como um número.

você pode usar o seguinte método para testar se qualquer string pode ser analisada como Integer:

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

Quanto à sua pergunta, o que é NumberFormatException: é lançado para indicar que o aplicativo tentou converter uma string em um dos tipos numéricos, mas que a string não possui o formato apropriado. (ref – http://docs.oracle.com/javase/7/docs/api/java/lang/NumberFormatException.html )

A Exceção vem em seu código, onde você converte a String em um Integer:

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

onde você passa um String como “Ace of Clubs” que não é possível converter como inteiro, então ele lança Number Format Exception. Você pode usar,

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