首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是NumberFormatException ?我如何修复它?

什么是NumberFormatException ?我如何修复它?
EN

Stack Overflow用户
提问于 2016-10-04 18:31:04
回答 9查看 68.7K关注 0票数 28
代码语言:javascript
复制
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循环:

代码语言:javascript
复制
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
EN

回答 9

Stack Overflow用户

发布于 2016-10-04 18:38:45

代码语言:javascript
复制
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

意思是:

代码语言:javascript
复制
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"解析为int,而这是Java无法使用Integer.parseInt方法完成的。Java提供了漂亮的堆栈跟踪,它可以准确地告诉您问题所在。您正在寻找的工具是调试器,使用断点将允许您在选定的时刻检查应用程序的状态。

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

代码语言:javascript
复制
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

异常是在程序执行过程中发生的一种事件,它扰乱了程序指令的正常流动。

-Documentation

Integer#parseInt中的构造函数和用法

代码语言:javascript
复制
static NumberFormatException forInputString(String s) {
    return new NumberFormatException("For input string: \"" + s + "\"");
}

public NumberFormatException (String s) {
    super (s);
}

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

代码语言:javascript
复制
if (s == null) {
    throw new NumberFormatException("null");
}

或者稍后,如果输入String s的格式不可解析:

代码语言:javascript
复制
throw NumberFormatException.forInputString(s); 

什么是 NumberFormatException**?**

抛出

以指示应用程序已尝试将字符串转换为其中一种数字类型,但该字符串的格式不正确。

-Documentation

NumberFormatException extends IllegalArgumentException.它告诉我们它是更加专门化的IllegalArgumentException。实际上,它是用来强调尽管参数类型是正确的(String),但String的内容不是数字(a,b,c,d,e,f在十六进制中被认为是数字,需要时是合法的)。

我该如何修复它?

好吧,不要纠正它被抛出的事实。它被抛出是件好事。有一些事情你需要考虑:

我是否可以阅读导致字符串看起来像数字的stacktrace?

  • Is null

  • Does
  1. String Is it 'my Exception‘or user's
  2. to be continued

<Exception>G257

Ad.1.

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

Ad.2.

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

在StackOverflow null 上很好地描述了解决意外线程的描述。

Ad.3.

如果:后面被引用的String在您看来像一个数字,则可能存在您的系统无法解码的字符或看不见的空格。显然," 6"不能像"123 "一样被解析,这是因为有空格。但它可能会发生,String看起来像"6",但实际上它的长度会比你能看到的位数大。

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

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

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

Ad.4.

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

我现在能做什么?好的,Java为我们提供了try-catch,你可以这样做:

代码语言:javascript
复制
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.
}
票数 44
EN

Stack Overflow用户

发布于 2016-10-12 23:49:04

什么是NumberFormatException

引发此异常是为了指示应用程序已尝试将string转换为数字类型之一,但string没有适当的格式。

在您的例子中,根据堆栈跟踪,这个异常是由Integer.parseInt(String)抛出的,这意味着提供的String不包含可解析的integer。根据堆栈跟踪,这仍然是因为您试图将String "Ace of Club“解析为整数,但由于它不是整数的String表示,因此无法工作。

如何修复它?

最简单和通用的方法是捕获异常NumberFormatException

代码语言:javascript
复制
int value = -1;
try {
    value = Integer.parseInt(myString);
} catch (NumberFormatException e) {
    // The format was incorrect
}

它可以工作,但捕获异常很慢,因为它需要构建调用堆栈来创建Exception,这是代价高昂的,所以如果你可以避免它,就去做吧。此外,您将需要适当地管理异常,这并不总是显而易见的。

或者,您可以使用regular expression首先检查String matches是否带有Integer,但它很容易出错,因为您很容易使用错误的regular expression

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

因此,如果您决定为您的卡使用专用类,您的代码可能是:

代码语言:javascript
复制
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,因为现有的花色和花色数量有限。

代码语言:javascript
复制
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数组,并且可以初始化为next:

代码语言:javascript
复制
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))

代码语言:javascript
复制
List<Card> allCards = Arrays.asList(cards);
Collections.shuffle(allCards);
allCards.toArray(cards);

然后,您将能够使用cards[index].getRank().getValue()直接访问您的卡的值,而不会冒着获得异常的风险(如果您没有使用适当的索引,则IndexOutOfBoundsException除外)。

票数 10
EN

Stack Overflow用户

发布于 2016-10-04 18:37:45

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

代码语言:javascript
复制
int first_value = Integer.parseInt(cards[index]);
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39849984

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档