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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:29:59  来源:igfitidea点击:

What is a NumberFormatException and how can I fix it?

javaarrayswhile-loopnumberformatexception

提问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 Clubsto Integer.

看起来cards[]String数组,而您正在尝试转换Ace of ClubsInteger

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 intwhat 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"intJava 无法使用 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 Exceptionin Java?

ExceptionJava中的an是什么?

An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.

异常是在程序执行期间发生的事件,它会中断程序指令的正常流程。

-Documentation

-文件

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 NumberFormatExceptionis thrown from Integer#parseInt:

它们对于理解如何阅读堆栈跟踪很重要。看看是如何NumberFormatException抛出的Integer#parseInt

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

or later if the format of the input String sis 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.

抛出以指示应用程序已尝试将字符串转换为数字类型之一,但该字符串没有适当的格式。

-Documentation

-文件

NumberFormatExceptionextendsIllegalArgumentException. 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 Stringwasn't numeric (a,b,c,d,e,f are considered digits in HEX and are legal when needed).

NumberFormatExceptionextendsIllegalArgumentException. 它告诉我们它更专业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:

我如何解决它?
好吧,不要解决它被抛出的事实。扔了就好了。您需要考虑以下几点:

  1. Can I read the stacktrace?
  2. Is the Stringwhich causes an Exceptiona null?
  3. Does it look like a number?
  4. Is it 'my string' or user's input?
  5. to be continued
  1. 我可以阅读堆栈跟踪吗?
  2. String哪个导致Exceptiona null
  3. 它看起来像一个数字吗?
  4. 它是“我的字符串”还是用户的输入?
  5. 未完待续

Ad. 1.

广告。1.

The first line of a message is an information that the Exception occurred and the input Stringwhich 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 nulls is well described on StackOverflow thread What is a NullPointerException and how can I fix it?.

nullStackOverflow 线程What is a NullPointerException and howto fix it?上很好地描述了解决意外s 的描述 .

Ad. 3.

广告。3.

If the Stringthat 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 Stringwill 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.printlnand print the length of the Stringyou'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 intor long. You might want to try new BigDecimal(<str>).

另一种情况是,当号码有很多位数时。可能是,它太大或太小而无法容纳intlong。你可能想试试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-catchyou 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 stringto one of the numeric types, but that the stringdoes 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 Stringdoes 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 Stringrepresentation 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 Exceptionwhich 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 expressionto check first if the Stringmatcheswith an Integerbut it is quite error prone as you could easily use a wrong regular expression.

或者您可以先使用 aregular expression来检查是否Stringmatches带有 anInteger但它很容易出错,因为您很容易使用错误的regular expression.



In your case, a more OO approach should be used instead of dealing with String, for example you could use a classor an enumto represent your cards instead of using simple Stringbecause 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 enumsince 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 cardswould be an array of Cardinstead 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 Listof 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 IndexOutOfBoundsExceptionif 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 NumberFormatExceptionmeans that Integer.parseInt()couldn't translate the string into a number.

ANumberFormatException表示Integer.parseInt()无法将字符串转换为数字。

I would suggest one of two options:

我会建议以下两种选择之一:

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

  2. 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 called CardToInt()(or whatever), and use that function instead of Integer.parseInt().

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

  2. 自己解析字符串。这可能更容易,因为你已经用这些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”似乎根本不是整数。