我如何优雅地使java.util.Scanner再次等待输入?

问题描述:

我有一个程序的以下部分,它模拟了一个非常基本的菜单。我如何优雅地使java.util.Scanner再次等待输入?

while (true) { 
    int selection; 
    try { 
     selection = scanner.nextInt(); 
    } catch (Exception e) { 
     selection = -1; 
    } 
    switch (selection) { 
    case 0: 
     System.exit(0); 
    default: 
     System.out.println("No valid selection!"); 
    } 
} 

现在,每当我输入的整数,所述selection设为-1并打印错误消息。然而,循环继续不断,Scanner不等待任何输入。

如何让它再次等待?如何在这里更好地处理格式错误的用户输入?

Scanner不能读的东西,有问题的数据是从流,这意味着任何后续的读取会再次失败,直到数据删除已清除。

为了解决这个问题,你可以,如果失败,只是读的东西,而忽略结果:

try { 
    selection = scanner.nextInt(); 
} catch (Exception e) { 
    selection = -1; 
    scanner.next(); // discard the input 
} 

使某些用户输入退出/打破while循环。就像用户在循环停止时输入“Exit”一样。

除此之外,你可以这样做:

catch (Exception e) { 
    selection = -1; 
} 
switch (selection) { 
case 0: 
    System.exit(0); 
default: 
    System.out.println("No valid selection!"); 
    System.out.println("Try again!"); 
    selection = scanner.nextInt();   
} 
+0

的问题是什么@EtiennedeMartel描述了他的答案; 'nextInt()'不会在失败时从扫描器中移除令牌,因此他的程序进入无限循环(就像你的那样)。 –

+0

这不起作用。如果'nextInt()'失败,则任何对'nextInt()'的调用都将再次失败,直到数据从流中被移除。 –

+0

是的,这不起作用,只是抛出后续的异常。 – slhck

不知道抛出和捕获的异常是否在你的情况相关。

尝试:

boolean isValid = false; 
int selection; 
while(!isValid) { 
    isValid = scanner.hasNextInt(); 
    if(!isValid) { 
     System.out.println("No valid selection!"); 
     scanner.next(); 
    } else { 
     selection = scanner.nextInt(); 
    } 
} 
if(selection == 0) { 
    System.exit(0); 
} 
+1

这是一个相当不错的方法,除了你的cheesy'isInteger()'方法;)'Integer.parseInt(String i)'为你做这件事,并且如果它不是一个整数则抛出一个异常。 (这正是使用'scanner.nextInt()'时发生的情况......) –

+0

我知道,但'Integer.parseInt'不应该用于测试String是否为int ;-)无论如何,一个是免费的以他想要的方式实现'isInteger'方法:) –

+0

Java似乎不同意你,因为这正是'Scanner'所做的。 (我个人也同意Josh Bloch的观点,即异常只能用于例外情况)。然而,我试图做的一点是,约定是,如果你期待'int',可以使用'nextInt()'并捕获异常(在catch中用'next()'丢弃该标记) 。更好的是,你可以使用'hasNextInt()'完全避免异常处理。没有理由在这里编写你自己的任何实现。 –