什么是NumberFormatException,如何解决?

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) 

我的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 
 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 

手段:

 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 

换句话说,您试图将"Ace of Clubs"parsing为一个int这是Java无法用Integer.parseInt方法完成的。 Java已经提供了美丽的堆栈跟踪,告诉你到底是什么问题。 您正在寻找的工具是debugging器 ,使用断点将允许您在选定时刻检查应用程序的状态

如果您想使用parsing ,解决scheme可能是以下逻辑:

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

Java中的Exception是什么?

一个例外是在程序执行过程中发生的一个事件,它会中断程序指令的正常stream程。

– 文件

Integer#parseInt构造函数和用法

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

它们对于理解如何读取堆栈跟踪非常重要。 看看如何从Integer#parseInt抛出NumberFormatException

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

或者如果input的String s格式不可parsing:

 throw NumberFormatException.forInputString(s); 

什么是NumberFormatException

抛出以指示应用程序试图将string转换为其中一种数字types,但该string没有适当的格式。

– 文件

NumberFormatException extends IllegalArgumentException 。 它告诉我们这是更专业的IllegalArgumentException 。 事实上,它用于突出显示,尽pipe参数types是正确的( String ),但String的内容不是数字( a,b,c,d,e,f被认为是HEX中的数字,在需要时是合法的 )。

我该如何解决?
那么,不要纠正它被抛出的事实。 这是很好的,它被抛出。 有一些事情你需要考虑:

  1. 我可以读取堆栈跟踪吗?
  2. 是引起ExceptionString是否为null
  3. 它看起来像一个数字吗?
  4. 是“我的string”还是用户的input?
  5. 未完待续

广告。 1。

消息的第一行是发生exception的信息和导致问题的inputString 。 string总是如下:被引用( "some text" )。 然后你就会对从头读取堆栈跟踪感兴趣,因为前几行通常是NumberFormatException的构造函数,parsing方法等等。最后,你有一个方法,在这个方法中你犯了一个错误。 它将被指出在哪个文件中被调用,以及在哪个方法中。 即使是一条线将被连接。 你会看到的。 上面是如何读取堆栈跟踪的例子。

广告。 2。

当你看到,而不是"For input string:"和input,有一个null而不是"null" ),这意味着,你试图通过空引用的数字。 如果你真的想把它当作0或者任何其他的数字,你可能会对我在StackOverflow上的另一篇文章感兴趣。 它在这里可用。

解决意外的null的描述在StackOverflow线程上有很好的描述什么是NullPointerException,我该如何解决它?

广告。 3。

如果在你看来,被引用的后面的String看起来像一个数字,那么可能有一个系统不能解码的字符或一个看不见的空白。 显然" 6"不能parsing, "123 "不能parsing。 这是因为空间。 但是可能会发生, String看起来像"6"但实际上它的长度将会大于您可以看到的位数。

在这种情况下,我build议使用debugging器或至lessSystem.out.println并打印你想分析的String的长度。 如果显示的位数超过位数,请尝试将stringToParse.trim()传递给parsing方法。 如果不能工作,则复制整个string,然后使用在线解码器进行解码。 它会给你所有字符的代码。

还有一个我最近在StackOverflow上find的例子,你可能会看到,input看起来像一个数字,例如"1.86" ,它只包含这4个字符,但错误仍然存​​在。 请记住,只能使用#整数#parseInt#parsing整数。 为了parsing十进制数字,应该使用Double#parseDouble

广告。 4。

最后我们来到我们同意的地方,当用户input“abc”作为数字string时,我们不能避免这种情况。 为什么? 因为他可以。 在幸运的情况下,这是因为他是一名testing人员或者只是一个极客。 在不好的情况下,它是攻击者。

我现在能做什么? 那么,Java给我们try-catch你可以做到以下几点:

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

什么是NumberFormatException

抛出此exception以指示应用程序试图将string转换为其中一种数字types,但该string没有适当的格式。

在你的情况下,根据你的堆栈跟踪,这个exception是由Integer.parseInt(String)引发的,这意味着提供的String不包含可分析的integer 。 而且仍然根据堆栈跟踪,这是因为您试图将StringAce of Ace ”parsing为无法工作的整数,因为它不是整数的String表示forms。

如何解决它?

最简单和通用的方法是捕获exceptionNumberFormatException

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

它会工作,但捕捉exception是缓慢的,因为它需要build立调用堆栈来创buildException是昂贵的,所以如果你可以避免它做到这一点。 此外,您将需要妥善pipe理exception,这并不总是显而易见的。

或者你可以使用一个regular expression来首先检查String是否与Integer matches ,但这很容易出错,因为你可以很容易地使用一个错误的regular expression


在你的情况下,应该使用更多的面向对象的方法,而不是处理String ,例如,你可以使用classenum来表示你的卡,而不是使用简单的String因为它更容易出错,因为你已经注意到了。

所以如果你决定为你的卡使用专门的类,你的代码可能是:

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

对于一张牌的花色和等级,我们可以使用一个enum因为现有的队伍和套装数量是有限的。

 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 } 

然后cards将是一个Card数组,而不是一个String数组,可以被初始化为下一个:

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

如果你需要洗牌你的卡片,你可以继续下一步(请注意,如果你决定使用卡片List而不是数组,只需使用Collections.shuffle(list)

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

然后,您将可以直接访问cards[index].getRank().getValue()而不会冒险获得exception(如果没有使用正确的索引, IndexOutOfBoundsException除外)。

看起来像cards[]string数组,你正试图将Ace of Clubs转换为整数

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

当您尝试parsing某些不是数字string的input时会发生。

在你的情况下,你试图parsing一个string(没有数字)作为整数。 因为它不可能发生NumberFormatExceptionexception。

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

NumberFormatException是Java不得不说你的方式“我试图将一个string转换为int,我不能这样做”。

在你的exception跟踪中,你可以阅读

 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) 

基本上,这意味着在你的代码的第68行调用Integer.parseInt方法传递“Ace of Clubs”作为参数。 这个方法需要一个以String表示的整型值,例如“4”,所以方法会抛出一个NumberFormatExceptionexception,因为“Ace of Clubs”似乎并不是一个整数。

第一件事情就是让我一个循环(没有双关语意思)是当它需要0-52的时候,把值限制在1-13。 同样你的逻辑价值总是更高。 更好的方法是使用数字发生器。 这是我的代码使用数字生成器(或Java随机):

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

至于NumberFormatException,我认为Nicolas Filotto做了很好的解释。

NumberFormatException意味着Integer.parseInt()不能将string转换为数字。

我会build议两种select之一:

  1. 将卡封装为名称(string)/值(int)组合。 使用该值进行比较,并使用名称向用户显示信息。 Cards[]然后变成卡片的列表,而不是string。

  2. 自己parsingstring。 这可能会更容易,因为你已经用if(cards[index].startsWith("Ace")) { value = 1; } if(cards[index].startsWith("Ace")) { value = 1; }位。 你可以将它们移动到名为CardToInt() (或其他)的函数中,并使用该函数而不是Integer.parseInt()

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

在写上面的语句时,你试图把“Ace of Clubs”parsing成一个数字。

您可以使用以下方法来testing是否有任何string可以被parsing为整数:

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

关于你的问题,什么是NumberFormatException:它被抛出,表示应用程序试图将string转换为其中一种数字types,但该string没有适当的格式。 (参考 – http://docs.oracle.com/javase/7/docs/api/java/lang/NumberFormatException.html

exception出现在您的代码中,您将string转换为整数:

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

在那里你传递一个string作为“俱乐部的王牌”这是不可能转换为整数,所以它会引发数字格式exception。 您可以使用,

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