2

我编写了这个简单的代码来获取一个双精度并一直询问直到给出一个,但是当你给出一个字符串时,它只会变成一个无限循环,我不知道为什么。它有这种行为的任何理由?

Scanner scanner = new Scanner(System.in);   
double x = 0.0d;

while (true) {
    try {
        System.out.println("Gimme a double:");

        x = scanner.nextDouble();
        break;
    } catch (InputMismatchException e) {}           
}

System.out.println(x);
4

3 回答 3

7

double如果最初输入了无效值,它将成为无限循环。然后控制进入异常块。因为Scanner#nextDouble不消耗换行符,所以这些值被反复传递给语句

x = scanner.nextDouble();

这不会阻止已经收到输入。这会导致无限循环。

而不是有一个空的异常块,Scanner#nextLine应该用来消耗换行符。

} catch (InputMismatchException e) {
    System.out.println("Error found: " + scanner.nextLine() + " continuing...");
}

这样该Scanner#nextDouble行将IO在下一次迭代中阻塞。

于 2013-05-01T00:03:44.427 回答
2

根据 javadocs Scanner#nextDouble,如果转换不成功,则不会消耗字符double(但如果转换成功,则不会消耗字符):

将输入的下一个标记扫描为双精度。如果下一个标记无法转换为有效的双精度值,此方法将抛出 InputMismatchException。如果翻译成功,扫描仪会超过匹配的输入。

程序的示例输出:

$ java Main
Gimme a double:
3.5
3.5
$ java Main
Gimme a double:
blah
Gimme a double:
Gimme a double:
Gimme a double:
Gimme a double:
Gimme a double:
Gimme a double:
(Infinite loop here)

您必须自己使用这些字符,最好是在异常处理程序中:

} catch (InputMismatchException e) {
    System.out.println("Not a double: " + scanner.nextLine());
}

更改程序的示例输出:

$ java Main
Gimme a double:
blah
Skipped Past: blah
Gimme a double:
3.56
3.56
于 2013-05-01T00:10:02.920 回答
1

Reimeus 正确地说明了为什么会发生无限循环。scanner.nextLine()您可以通过调用catch 块来修复它:

public static void main(String[] args) throws IllegalArgumentException,
        IllegalAccessException {
    /*
     * StackTest t = new StackTest();
     * 
     * for(Field f :t.getClass().getDeclaredFields()){
     * System.out.println(f.get(t)); }
     */

    Scanner scanner = new Scanner(System.in);
    double x = 0.0d;

    while (true) {
        try {
            System.out.println("Gimme a double:");

            x = scanner.nextDouble();
            break;
        } catch (InputMismatchException e) {
            scanner.nextLine();
        }
    }

    System.out.println(x);
}
于 2013-05-01T00:08:00.067 回答