Java 什么是 NumberFormatException 以及如何修复它?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39849984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is a NumberFormatException and how can I fix it?
提问by 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.1\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)
My While Loop:
我的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
回答by Vivek G
Looks like cards[]
is Stringarray and you are trying to convert Ace of Clubs
to Integer.
看起来cards[]
是String数组,而您正在尝试转换Ace of Clubs
为Integer。
int first_value = Integer.parseInt(cards[index]);
回答by xenteros
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.1\executor-snippets\run.xml:53: Java returned: 1
means:
方法:
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
In other words, you tried to parse "Ace of Clubs"
to an int
what Java can't do with method Integer.parseInt
. Java has provided beautiful stacktrace which tells you exactly what the problem is. The tool you're looking for is debuggerand using breakpointswill allow you to inspect the stateof you application at the chosen moment.
换句话说,您尝试解析"Ace of Clubs"
为int
Java 无法使用 method 执行的操作Integer.parseInt
。Java 提供了漂亮的堆栈跟踪,它可以准确地告诉您问题是什么。您正在寻找的工具是调试器,使用断点可以让您在所选时刻检查应用程序的状态。
The solution might be the following logic in case you want to use parsing:
如果您想使用解析,解决方案可能是以下逻辑:
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
}
}
What is an Exception
in Java?
Exception
Java中的an是什么?
An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.
异常是在程序执行期间发生的事件,它会中断程序指令的正常流程。
-文件
Constructors and usage in Integer#parseInt
构造函数和用法 Integer#parseInt
static NumberFormatException forInputString(String s) {
return new NumberFormatException("For input string: \"" + s + "\"");
}
public NumberFormatException (String s) {
super (s);
}
They are important for understanding how to read the stacktrace. Look how the NumberFormatException
is thrown from Integer#parseInt
:
它们对于理解如何阅读堆栈跟踪很重要。看看是如何NumberFormatException
抛出的Integer#parseInt
:
if (s == null) {
throw new NumberFormatException("null");
}
or later if the format of the input String s
is not parsable:
或稍后如果输入的格式String s
不可解析:
throw NumberFormatException.forInputString(s);
What is a NumberFormatException
?
什么是NumberFormatException
?
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.
抛出以指示应用程序已尝试将字符串转换为数字类型之一,但该字符串没有适当的格式。
-文件
NumberFormatException
extends
IllegalArgumentException
. It tells us that it's more specialized IllegalArgumentException
. Indeed, it's used for highlighting that although, the argument type was correct (String
) the content of the String
wasn't numeric (a,b,c,d,e,f are considered digits in HEX and are legal when needed).
NumberFormatException
extends
IllegalArgumentException
. 它告诉我们它更专业IllegalArgumentException
。实际上,它用于强调虽然参数类型是正确的 ( String
) 的内容String
不是数字(a,b,c,d,e,f 被认为是十六进制中的数字,并且在需要时是合法的)。
How do I fix it?
Well, don't fix the fact that it's thrown. It's good that it's thrown. There are some things you need to consider:
我如何解决它?
好吧,不要解决它被抛出的事实。扔了就好了。您需要考虑以下几点:
- Can I read the stacktrace?
- Is the
String
which causes anException
anull
? - Does it look like a number?
- Is it 'my string' or user's input?
- to be continued
- 我可以阅读堆栈跟踪吗?
- 是
String
哪个导致Exception
anull
? - 它看起来像一个数字吗?
- 它是“我的字符串”还是用户的输入?
- 未完待续
Ad. 1.
广告。1.
The first line of a message is an information that the Exception occurred and the input String
which caused the problem. The String always follows :
and is quoted ("some text"
). Then you become interested in reading the stacktrace from the end, as the first few lines are usually NumberFormatException
's constructor, parsing method etc. Then at the end, there is your method in which you made a bug. It will be pointed out in which file it was called and in which method. Even a line will be attached. You'll see. The example of how to read the stacktrace is above.
消息的第一行是发生异常的信息以及String
导致问题的输入。字符串总是跟:
在后面并被引用 ( "some text"
)。然后你开始对从最后阅读堆栈跟踪感兴趣,因为前几行通常是NumberFormatException
的构造函数、解析方法等。然后在最后,你的方法是你犯了错误。将指出它是在哪个文件中调用的以及在哪个方法中调用的。甚至会附加一条线。你会看到的。上面是如何读取堆栈跟踪的示例。
Ad. 2.
广告。2.
When you see, that instead of "For input string:"
and the input, there is a null
(not "null"
) it means, that you tried to pass the null reference to a number. If you actually want to treat is as 0 or any other number, you might be interested in my another post on StackOverflow. It's available here.
当你看到,而不是"For input string:"
和输入,有一个null
(不是"null"
)这意味着,你试图将空引用传递给一个数字。如果您真的想将 is 视为 0 或任何其他数字,您可能会对我在 StackOverflow 上的另一篇文章感兴趣。它可以在这里找到。
The description of solving unexpected null
s is well described on StackOverflow thread What is a NullPointerException and how can I fix it?.
null
StackOverflow 线程What is a NullPointerException and howto fix it?上很好地描述了解决意外s 的描述 .
Ad. 3.
广告。3.
If the String
that follows the :
and is quoted looks like a number in your opinion, there might be a character which your system don't decode or an unseen white space. Obviously " 6"
can't be parsed as well as "123 "
can't. It's because of the spaces. But it can occure, that the String
will look like "6"
but actually it's length will be larger than the number of digits you can see.
如果您认为 and 后面String
的:
和 被引用看起来像一个数字,则可能存在您的系统无法解码的字符或看不见的空格。显然" 6"
不能解析,也不能解析"123 "
。这是因为空格。但是它可能String
会发生,看起来像"6"
但实际上它的长度会大于您可以看到的位数。
In this case I suggest using the debuggeror at least System.out.println
and print the length of the String
you're trying to parse. If it shows more than the number of digits, try passing stringToParse.trim()
to the parsing method. If it won't work, copy the whole string after the :
and decode it using online decoder. It'll give you codes of all characters.
在这种情况下,我建议使用调试器或至少System.out.println
打印String
您尝试解析的长度。如果它显示的位数多于位数,请尝试传递stringToParse.trim()
给解析方法。如果它不起作用,请在 之后复制整个字符串:
并使用在线解码器对其进行解码。它会给你所有字符的代码。
There is also one case which I have found recently on StackOverflow
, that you might see, that the input looks like a number e.g. "1.86"
and it only contains those 4 characters but the error still exists. Remember, one can only parse integers with #Integer#parseInt#. For parsing decimal numbers, one should use Double#parseDouble
.
我最近还发现了一种情况StackOverflow
,您可能会看到,输入看起来像一个数字,例如"1.86"
,它只包含这 4 个字符,但错误仍然存在。请记住,只能使用#Integer#parseInt# 解析整数。对于解析十进制数,应该使用Double#parseDouble
.
Another situation is, when the number has many digits. It might be, that it's too large or too small to fit int
or long
. You might want to try new BigDecimal(<str>)
.
另一种情况是,当号码有很多位数时。可能是,它太大或太小而无法容纳int
或long
。你可能想试试new BigDecimal(<str>)
。
Ad. 4.
广告。4.
Finally we come to the place in which we agree, that we can't avoid situations when it's user typing "abc" as a numeric string. Why? Because he can. In a lucky case, it's because he's a tester or simply a geek. In a bad case it's the attacker.
最后我们来到了我们同意的地方,我们无法避免用户输入“abc”作为数字字符串的情况。为什么?因为他可以。幸运的是,那是因为他是测试人员,或者只是个极客。在最坏的情况下,它是攻击者。
What can I do now?Well, Java gives us try-catch
you can do the following:
我现在能做什么?好吧,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.
}
回答by Nicolas Filotto
What is a NumberFormatException
?
什么是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.
抛出此异常表示应用程序已尝试将 a 转换为
string
数字类型之一,但string
没有适当的格式。
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.
在您的情况下,根据您的堆栈跟踪,抛出此异常Integer.parseInt(String)
意味着所提供的String
不包含 parseable integer
。并且仍然根据堆栈跟踪,这是由于您试图将String
“俱乐部王牌”解析为一个无法工作的整数,因为它不是String
整数的表示。
How to fix it?
如何解决?
The simplest and generic way is to catch the exception NumberFormatException
最简单通用的方法是捕获异常 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.
它会起作用,但捕获异常很慢,因为它需要构建调用堆栈来创建Exception
代价高昂的调用堆栈,因此如果可以避免它,请执行此操作。此外,您需要正确管理异常,这并不总是很明显。
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
.
或者您可以先使用 aregular expression
来检查是否String
matches
带有 anInteger
但它很容易出错,因为您很容易使用错误的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.
在您的情况下,应该使用更面向对象的方法而不是处理String
,例如,您可以使用 aclass
或 anenum
来表示您的卡片,而不是使用 simple ,String
因为正如您已经注意到的那样,它更容易出错。
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.
对于卡片的花色和等级,我们可以使用 an,enum
因为现有的等级和花色数量有限。
public enum Rank {
ACE(1), TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), HEIGHT(8),
NINE(9), TEN(10), Hyman(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:
然后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]);
}
}
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
牌而不是一个阵列,只需使用Collections.shuffle(list)
)
List<Card> 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).
然后,您将能够直接访问您的卡的价值,cards[index].getRank().getValue()
而无需冒险获得异常(除非IndexOutOfBoundsException
您没有使用正确的索引)。
回答by thekodester
The very first thing that threw me for a loop (no pun intended) was you were limiting the value to 1-13 when it needs to be 0-52. Also with your logic the value was always be higher. A better approach is with a number generator. Here is my code using a number generator (or Java Random):
让我循环的第一件事(无意双关语)是当它需要为 0-52 时,您将值限制为 1-13。同样按照你的逻辑,价值总是更高。更好的方法是使用数字生成器。这是我使用数字生成器(或 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++;
}
}
As for the NumberFormatException I believe Nicolas Filotto did a good job explaining that.
至于 NumberFormatException,我相信 Nicolas Filotto 很好地解释了这一点。
回答by Anands23
The Exception comes in your code, where you convert the String to an Integer :
异常出现在您的代码中,您可以在其中将 String 转换为 Integer :
int first_value = Integer.parseInt(cards[index]);
where you pass a String as "Ace of Clubs"which is not possible to convert as integer,so it throws Number Format Exception. You can use,
您将字符串作为“俱乐部王牌”传递,该字符串无法转换为整数,因此会引发数字格式异常。您可以使用,
try {
....
// Your Code
....
}
catch(NumberFormatException e)
{
e.getMessage(); //You can use anyone like printStackTrace() ,getMessage() to handle the Exception
}
回答by Andrew Tofelt
A NumberFormatException
means that Integer.parseInt()
couldn't translate the string into a number.
ANumberFormatException
表示Integer.parseInt()
无法将字符串转换为数字。
I would suggest one of two options:
我会建议以下两种选择之一:
Encapsulate cards as a name(string)/value(int) combo. Use the value to do comparisons, and the name to present info to the user.
Cards[]
then becomes a list of cards, not strings.Parse the strings yourself. Which may be easier, since you've already done it with the
if(cards[index].startsWith("Ace")) { value = 1; }
bits. You can move those into a function calledCardToInt()
(or whatever), and use that function instead ofInteger.parseInt()
.
将卡片封装为名称(字符串)/值(整数)组合。使用值进行比较,使用名称向用户显示信息。
Cards[]
然后变成卡片列表,而不是字符串。自己解析字符串。这可能更容易,因为你已经用这些
if(cards[index].startsWith("Ace")) { value = 1; }
位完成了。您可以将它们移动到一个名为CardToInt()
(或其他)的函数中,并使用该函数而不是Integer.parseInt()
.
回答by Rajesh Gopu
java.lang.NumberFormatException
occurs when you are trying to parse some input which not a Number string.
当您尝试解析一些不是数字字符串的输入时发生。
In your case your trying to parse a string (which not has number )as Integer. As its not possible NumberFormatException exception occured.
在您的情况下,您试图将字符串(没有 number )解析为整数。由于它不可能出现 NumberFormatException 异常。
int first_value = Integer.parseInt(cards[index]);//cards[index] value should be //number string "123" not "abc"
回答by roopaliv
int first_value = Integer.parseInt(cards[index]);
while writing the above statement, you are trying to parse "Ace of Clubs" as a number.
在编写上述语句时,您试图将“俱乐部王牌”解析为一个数字。
you can use the following method to test if any string can be parsed as Integer:
您可以使用以下方法来测试是否可以将任何字符串解析为整数:
boolean tryParseInt(String value) {
try {
Integer.parseInt(value);
return true;
} catch (NumberFormatException e) {
return false;
}
}
Regarding your question, what is NumberFormatException : It 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. (ref -http://docs.oracle.com/javase/7/docs/api/java/lang/NumberFormatException.html)
关于您的问题,什么是 NumberFormatException :抛出它表示应用程序已尝试将字符串转换为数字类型之一,但该字符串没有适当的格式。(参考 - http://docs.oracle.com/javase/7/docs/api/java/lang/NumberFormatException.html)
回答by jmlotero
A NumberFormatException is the way Java has to say you "I tried to convert a String to int and I could not do it".
NumberFormatException 是 Java 必须对您说“我试图将 String 转换为 int 但我做不到”的方式。
In your exception trace you can read
在您的异常跟踪中,您可以阅读
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)
Basically, it means that at the line 68 of your code you call to the Integer.parseInt method passing "Ace of Clubs" as paremeter. This method expects a integer value represented as String, e.g. "4", so method complains throwing a NumberFormatException because "Ace of Clubs" does not seem a integer at all.
基本上,这意味着在代码的第 68 行,您调用 Integer.parseInt 方法并传递“Ace of Clubs”作为参数。此方法需要一个表示为字符串的整数值,例如“4”,因此该方法会抱怨抛出 NumberFormatException,因为“Ace of Clubs”似乎根本不是整数。