什么是 NumberFormatException,我该如何解决?

错误信息:线程main"java.lang.NumberFormatException 中的异常:对于输入字符串:Ace of Clubs"在 java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)在 java.lang.Integer.parseInt(Integer.java:580)在 java.lang.Integer.parseInt(Integer.java:615)在 set07102.Cards.main(Cards.java:68)C:UsersqasimAppDataLocalNetBeansCache8.1executor-snippetsun.xml:53:Java 返回:1构建失败(总时间:0 秒)

我的 While 循环:

while (response != 'q' && index < 52) {System.out.println(cards[index]);int first_value = Integer.parseInt(cards[index]);整数值 = 0;//添加一个扫描器扫描仪扫描仪=新扫描仪(System.in);System.out.println("下一张牌是高还是低?,要退出请按q");字符串猜测 =scanner.nextLine();if(cards[index].startsWith("Ace")) { value = 1;}if(cards[index].startsWith("2")) { value = 2;}if(cards[index].startsWith("3")) { value = 3;}//检查 4-10if(cards[index].startsWith("Queen")){ value = 11;}if(cards[index].startsWith("King")){ value = 12;}if(guess.startsWith("h")){if(value > first_value){ System.out.println("你的回答是对的,weldone!");}else { System.out.println("你回答错了,再试一次!");}} 否则 if(guess.startsWith("l")){if(value < first_value) { System.out.println("你答对了,再试一次!");}else { System.out.println("你回答错了,再试一次!");}} else { System.out.println("你的无效,再试一次!");}扫描仪.close();索引++;}//while循环结束

解决方案

错误信息:线程main"java.lang.NumberFormatException 中的异常:对于输入字符串:Ace of Clubs"在 java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)在 java.lang.Integer.parseInt(Integer.java:580)在 java.lang.Integer.parseInt(Integer.java:615)在 set07102.Cards.main(Cards.java:68)C:UsersqasimAppDataLocalNetBeansCache8.1executor-snippetsun.xml:53:Java 返回:1

意思是:

出现错误.我们尽力为您提供尽可能多的信息这是主线程中的异常.它被称为 NumberFormatException 并且在输入Ace of Clubs"时发生.在 NumberFormatException.java 的第 65 行,它是一个构造函数,它是从 Integer.parseInt() 调用的,它位于第 580 行的文件 Integer.java 中,从第 615 行的文件 Integer.java 中的 Integer.parseInt() 调用,它是从第 68 行文件 Cards.java 中的方法 main 调用的.它导致退出代码1

换句话说,您试图将 "Ace of Clubs" 解析为 int,而 Java 无法使用方法 Integer.parseInt.Java 提供了漂亮的堆栈跟踪,它可以准确地告诉您问题所在.您正在寻找的工具是 debugger,使用 breakpoints 可以让您在选定的时刻检查应用程序的状态.

如果您想使用解析,解决方案可能是以下逻辑:

if (cards[index].startsWith("Ace"))值 = 1;else if (cards[index].startsWith("King"))值 = 12;else if (cards[index].startsWith("Queen"))值 = 11;...别的 {尝试 {Integer.parseInt(string.substring(0, cards[index].indexOf(" ")));} 捕捉(NumberFormatException e){//出问题了}}

什么是 Java 中的 Exception?

<块引用>

异常是一个事件,它发生在一个事件的执行过程中程序,这会破坏程序指令的正常流程.

-文档

Integer#parseInt

中的构造函数和用法

静态 NumberFormatException forInputString(String s) {return new NumberFormatException("对于输入字符串:"" + s + """);}公共 NumberFormatException (String s) {超级(S);}

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

if (s == null) {抛出新的 NumberFormatException("null");}

如果输入 String s 的格式不可解析,则更晚:

throw NumberFormatException.forInputString(s);

什么是NumberFormatException?

<块引用>

抛出表明应用程序已尝试将字符串转换为其中一种数字类型,但该字符串没有适当的格式.

-文档

NumberFormatException extends IllegalArgumentException.它告诉我们它是更专业的 IllegalArgumentException.实际上,它用于突出显示,尽管参数类型正确(String)String 的内容不是数字(a,b,c,d,e,f 在 HEX 中被视为数字,在需要时是合法的).

我该如何解决?
好吧,不要修复它被抛出的事实.扔掉就好了.您需要考虑一些事项:

  1. 我可以读取堆栈跟踪吗?
  2. 导致 ExceptionStringnull 吗?
  3. 它看起来像一个数字吗?
  4. 是我的字符串"还是用户的输入?
  5. 待续

广告.1.

消息的第一行是发生异常的信息以及导致问题的输入String.字符串始终跟在 : 之后并被引用("some text").然后你开始对从最后读取堆栈跟踪感兴趣,因为前几行通常是 NumberFormatException 的构造函数、解析方法等.然后在最后,你的方法中出现了错误.将指出它是在哪个文件中调用的以及在哪个方法中调用的.甚至会附加一条线.你会看到的.上面是如何读取堆栈跟踪的示例.

广告.2.

当你看到,而不是 "For input string:" 和输入,有一个 null (not "null") 这意味着您试图将空引用传递给数字.如果您真的想将 is 视为 0 或任何其他数字,您可能会对我在 StackOverflow 上的另一篇文章感兴趣.此处提供.

解决意外 nulls 的描述在 StackOverflow 线程什么是 NullPointerException我该如何解决?.

广告.3.

如果 : 后面的 String 在您看来看起来像一个数字,则可能存在您的系统未解码或看不见的字符白色空间.显然 " 6" 不能被解析,而 "123 " 也不能.这是因为空间.但可能会发生,String 看起来像 "6" 但实际上它的长度会大于您可以看到的位数.

在这种情况下,我建议使用 debugger 或至少使用 System.out.println 并打印您正在使用的 String 的长度试图解析.如果显示的位数超过位数,请尝试将 stringToParse.trim() 传递给解析方法.如果它不起作用,请复制 : 之后的整个字符串并使用在线解码器对其进行解码.它会给你所有字符的代码.

我最近在 StackOverflow 上发现了一种情况,您可能会看到,输入看起来像一个数字,例如"1.86" 只包含这4个字符,但错误仍然存​​在.请记住,只能使用#Integer#parseInt# 解析整数.对于解析十进制数,应该使用 Double#parseDouble.

另一种情况是,当数字有很多位时.可能是它太大或太小而无法容纳 intlong.您可能想尝试 new BigDecimal(<str>).

广告.4.

最后我们达成了共识,我们无法避免用户输入abc"作为数字字符串的情况.为什么?因为他可以.在幸运的情况下,这是因为他是一名测试人员,或者只是一个极客.在糟糕的情况下,它是攻击者.

我现在能做什么? 那么,Java 为我们提供了 try-catch 你可以执行以下操作:

试试{i = Integer.parseInt(myString);} 捕捉(NumberFormatException e){e.printStackTrace();//不知何故用不正确的输入解决了这个问题.这取决于您的业务逻辑.}

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:UsersqasimAppDataLocalNetBeansCache8.1executor-snippetsun.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)

My While Loop:

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:UsersqasimAppDataLocalNetBeansCache8.1executor-snippetsun.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 debugger and using breakpoints will allow you to inspect the state of you application at the chosen moment.

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?

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

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:

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

or later if the format of the input String s is not parsable:

throw NumberFormatException.forInputString(s); 

What is a 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

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

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 String which causes an Exception a null?
  3. Does it look like a number?
  4. Is it 'my string' or user's input?
  5. to be continued

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

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

The description of solving unexpected nulls is well described on StackOverflow thread What is a NullPointerException and how can I fix it?.

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

In this case I suggest using the debugger or 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.

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.

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

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

What can I do now? Well, Java gives us try-catch you can do the following:

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

相关文章