2

我不明白这其中的逻辑。如果我运行此代码并输入一个非整数,例如字母 f,我会陷入输出两个 println 的无限循环,并且我没有机会再次向扫描仪输入整数……它只是不断吐出话到控制台。

public static void main(String[] args) {

    Scanner scan = new Scanner(System.in);//<<<<<SCANNER HERE
    int opponents = 0;
    boolean opponentsCreated = false;
    while(opponentsCreated == false)
    {
        try
        {
            System.out.print("How many players: ");
            int tempOpponents = scan.nextInt();
            if(tempOpponents > 0)
            {
                opponents = tempOpponents;
                opponentsCreated = true;
            }   
        }
        catch(InputMismatchException notAValidInt)
        {
            System.out.println("Not valid - must be a number greater than 0 ");
        }   
    }
}

但是,如果我只是将 Scanner 更改为在 while 循环中声明,那么程序会突然按预期工作:

public static void main(String[] args) {

    int opponents = 0;
    boolean opponentsCreated = false;
    while(opponentsCreated == false)
    {
        Scanner scan = new Scanner(System.in);//<<<<<SCANNER HERE
        try
        {
            System.out.print("How many players: ");
            int tempOpponents = scan.nextInt();
            if(tempOpponents > 0)
            {
                opponents = tempOpponents;
                opponentsCreated = true;
            }   
        }
        catch(InputMismatchException notAValidInt)
        {
            System.out.println("Not valid - must be a number greater than 0 ");
        }   
    }
}

老实说,我只是在这里坐了 2 个小时,试图弄清楚我的程序到底出了什么问题,结果却发现这是我声明我的 Scanner 的问题,即使在两个版本的代码中,Scanner 都没有超出范围。所以现在我真的很好奇为什么它会这样工作

4

2 回答 2

1

一个可能的问题是,当异常发生时,您可能会挂起行尾标记。如果您通过确保在需要时吞下行尾标记来处理此问题,您可能会没事。例如:

public static void main(String[] args) {

  Scanner scan = new Scanner(System.in);// <<<<<SCANNER HERE
  int opponents = 0;
  boolean opponentsCreated = false;
  while (opponentsCreated == false) {
     try {
        System.out.print("How many players: ");
        int tempOpponents = scan.nextInt();

        // line below corrected! 
        scan.nextLine();  // *** this might not be a bad idea either ***

        if (tempOpponents > 0) {
           opponents = tempOpponents;
           opponentsCreated = true;
        }
     } catch (InputMismatchException notAValidInt) {
        System.out.println("Not valid - must be a number greater than 0 ");
        scan.nextLine();  // ****** this is what you need here *****
     }
  }
}

顺便说一句,好问题!

于 2013-09-12T04:14:28.067 回答
1

添加到@HovercraftFullOfEels 答案:

根本原因是,如果出现上述异常,扫描仪位置不会移动。所以扫描仪一次又一次地读取相同的错误输入。引用JavaDoc

如果翻译成功,扫描仪会超过匹配的输入。

catch(InputMismatchException notAValidInt)
{
    scan.reset();
    System.out.println("Not valid - must be a number greater than 0 "); 
    //position is still 0
    scan.next(); //position is now 1
}

可视化:

Input:                  f______________
Scanner position:       ^______________

InputMismatchException  ^______________
scan.next()             _^_____________ 

相关来源(查看来源评论):

try {
            String s = next(integerPattern());
            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
                s = processIntegerToken(s);
            return Integer.parseInt(s, radix);
        } catch (NumberFormatException nfe) {
            position = matcher.start(); // don't skip bad token   
            throw new InputMismatchException(nfe.getMessage());
        }
于 2013-09-12T05:26:22.913 回答