如何防止扫描仪在输入错误类型时引发异常?

2022-09-03 13:17:21

下面是一些示例代码:

import java.util.Scanner;
class In
{
    public static void main (String[]arg) 
    {
    Scanner in = new Scanner (System.in) ;
    System.out.println ("how many are invading?") ;
    int a = in.nextInt() ; 
    System.out.println (a) ; 
    } 
}

如果我运行程序并给它一个类似,那么一切都会顺利。int4

另一方面,如果我回答,它不会嘲笑我的有趣笑话。相反,我得到这个(如预期):too many

Exception in thread "main" java.util.InputMismatchException
    at java.util.Scanner.throwFor(Scanner.java:819)
    at java.util.Scanner.next(Scanner.java:1431)
    at java.util.Scanner.nextInt(Scanner.java:2040)
    at java.util.Scanner.nextInt(Scanner.java:2000)
    at In.main(In.java:9)

有没有办法让它忽略不是int的条目,或者用“有多少人入侵”重新提示?我想知道如何做到这两点。


答案 1

您可以使用具有预验证的众多方法之一。hasNext*Scanner

    if (in.hasNextInt()) {
        int a = in.nextInt() ; 
        System.out.println(a);
    } else {
        System.out.println("Sorry, couldn't understand you!");
    }

这可以防止甚至被抛出,因为您始终确保阅读之前它将匹配。InputMismatchException


java.util.Scanner API

  • boolean hasNextInt():如果可以使用该方法将此扫描程序输入中的下一个标记解释为默认基数中的 int 值,则返回该值。扫描仪不会前进超过任何输入。truenextInt()

  • String nextLine()将此扫描仪前进到当前行,并返回跳过的输入。

请记住以粗体显示的部分。 不会前进超过任何输入。如果它返回,你可以通过调用来推进扫描仪,这不会抛出一个.hasNextInt()truenextInt()InputMismatchException

如果它返回,那么你需要跳过“垃圾”。最简单的方法是拨打 电话 ,可能是两次,但至少一次。falsenextLine()

为什么您可能需要执行两次操作:假设这是输入的输入:nextLine()

42[enter]
too many![enter]
0[enter]

假设扫描仪位于该输入的开头。

  • hasNextInt()为真,返回 ;扫描仪现在位于第一个.nextInt()42[enter]
  • hasNextInt()为 false,返回空字符串,第二个返回 ;扫描仪现在在第二个之后nextLine()nextLine()"too many!"[enter]
  • hasNextInt()为真,返回 ;扫描仪现在在第三个之前nextInt()0[enter]

下面是将其中一些内容放在一起的示例。您可以尝试使用它来研究其工作原理。Scanner

        Scanner in = new Scanner (System.in) ;
        System.out.println("Age?");
        while (!in.hasNextInt()) {
            in.next(); // What happens if you use nextLine() instead?
        }
        int age = in.nextInt();
        in.nextLine(); // What happens if you remove this statement?
        
        System.out.println("Name?");
        String name = in.nextLine();
        
        System.out.format("[%s] is %d years old", name, age);

假设输入是:

He is probably close to 100 now...[enter]
Elvis, of course[enter]

然后输出的最后一行是:

[Elvis, of course] is 100 years old

答案 2

总的来说,我真的非常不喜欢使用相同的库调用来阅读和解析。语言库似乎非常不灵活,通常无法按照自己的意愿弯曲。

从 System.in 中提取数据的第一步应该不会失败,因此请让它将其作为字符串读取到变量中,然后将该字符串变量转换为int。如果转换失败,请打印错误并继续。

当你用可能引发异常的东西包装你的流时,它会混淆整个混乱让你的流处于什么状态。


推荐