对于 InputMismatchException,catch 块 运行 多次

catch block is running multiple times for InputMismatchException

所以我在我的程序中使用了这段代码,每当我提供包含多个单词的输入时,编译器都会多次执行 catch 块。我也尝试过不同的方法,直到现在所有的努力都是徒劳的。

方法一:

Scanner scanner = new Scanner(System.in);
int size = 0;
while (true) 
{
    try
    {
        size = scanner.nextInt();
        break;
    }
    catch (InputMismatchException e) 
    {
        System.out.println("Enter valid input (Digit Only)");
        scanner.next();
        continue;
    }
}

方法二:

Scanner scanner = new Scanner(System.in);
int size = 0;
boolean bError = true;
while (bError) 
{
    if (scanner.hasNextInt())
        size = scanner.nextInt();
    else 
    {
        System.out.println("Enter valid input (Digit Only)");
        scanner.next();
        continue;
    }
    bError = false;
}

方法三:

Scanner scanner = new Scanner(System.in);
int size = 0;
while (true) 
{
    if (scanner.hasNextInt())
    size = scanner.nextInt();
else 
{
    scanner.next();
    System.out.println("Enter valid input (Digit Only)");
continue;
}
String sizeStr = Integer.toString(size);
Pattern pattern = Pattern.compile(new String ("^[0-9]*$"));
Matcher matcher = pattern.matcher(sizeStr);
if(matcher.matches())
{    
    break;
}
else
{
    System.out.println("Enter valid input (Digit Only)");
    continue;
}
}

方法四:

Scanner scanner = new Scanner(System.in);
int size = 0;
while (scanner.hasNext()) 
{
    if (scanner.hasNextInt())
    {
        size = scanner.nextInt();
        System.out.println(size);
        break;
    }
    else
    {
        System.out.println("Enter valid input (Digit Only)");
        scanner.next();
    }
}

我现在可以通过获取字符串输入然后将其解析为 int 来完成任务。但最初的疑问仍然是为什么它不能正常工作。下面的代码工作正常。

Scanner scanner = new Scanner(System.in);
int size = 0;
while (true) 
{
    try
    {
        String sizeStr = scanner.nextLine();
        size = Integer.parseInt(sizeStr);
        break;
    }
    catch (NumberFormatException e) 
    {
        System.out.println("Enter valid input (Digit Only)");
        scanner.next();
        continue;
    }
}

根据官方 Java 文档 (https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html):

A Scanner breaks its input into tokens using a delimiter pattern, 
which by default matches whitespace. The resulting tokens may then be 
converted into values of different types using the various next 
methods.

The scanner can also use delimiters other than whitespace.

默认情况下,除 nextLine() 之外,扫描仪 class 的所有 next*() 函数都读取下一个标记,而不是下一行。这意味着它会一直读取直到找到空白为止。如果你想读取一行中的所有标记,你需要使用 nextLine() 然后根据需要明确地格式化输入。

考虑这个输入:

abcd xyz

当您执行 scanner.nextInt() 或除 scanner.nextLine() 之外的任何 scanner.next*() 函数时,只会读取 "abcd",因为它是下一个令牌。当您执行 scanner.nextLine() 时,将读取当前行 "abcd xyz" 中的完整字符串,扫描程序会前进到下一行。

但是,如果您希望 nextInt() 函数读取整行,则可以将分隔符设置为新行 '\n'。

Scanner scan = new Scanner(System.in).useDelimiter("\n");

使用它,您可以获得您想要的行为。