尝试Catch InputMismatchException实际上没有捕获我的错误

时间:2018-02-04 12:42:58

标签: java inputmismatchexception

我从另一个程序中复制了完全相同的代码。每当输入故意的错误结果时,仍会发生InputMismatchException并且程序崩溃。

import java.util.*;
    public class Runner{
    public static void main (String args[]){
    Scanner sc = new Scanner(System.in);
    sc.useDelimiter("\n");
    Fixture f = new Fixture();
    boolean inputValid = false;
    int choice = 0;
    do{
        do {
            System.out.println("\f\t\tFootball Database");
            System.out.println("A utility to help make footballing events easier to manage.");
            System.out.println("");
            System.out.println("\t> Press 1 to manage players ");
            System.out.println("\t> Press 2 to manage teams");
            System.out.println("\t> Press 3 to manage coaches");
            System.out.println("\t> Press 4 to manage fixtures");
            System.out.println("\t> Press 5 to save database to file");
            System.out.println("\t> Press 6 to load database from file");
            System.out.println("\t> Press 7 to terminate program");
            System.out.println("");
            System.out.println("");
            System.out.println("©Thomas Camilleri 2017");
            try{
                choice = sc.nextInt();
                inputValid = true;
            }catch(InputMismatchException e){
                System.out.println("Invalid input");
                inputValid = false;
                sc.nextInt();
                sc.nextInt();
            }
        }while(inputValid == false);

2 个答案:

答案 0 :(得分:1)

以下是您的代码的重要部分:

        try {
            choice = sc.nextInt();   // NOT HERE
            inputValid = true;
        } catch(InputMismatchException e){
            System.out.println("Invalid input");
            inputValid = false;
            sc.nextInt();            // HERE
            sc.nextInt();
        }

如果您查看自己的堆栈跟踪,并查看行号,您会看到代码中发生异常的行是我用// HERE标记的行。

(编译并运行原始程序并查看堆栈跟踪以了解我的意思。将堆栈跟踪中的行号与源代码进行比较。)

如您所见,该行不在try { ... }块中。它位于异常处理程序块中。

发生的事情是您捕获了标记为// NOT HERE的行所引发的异常,然后再次调用sc.nextInt()// HERE)。第二个调用只是尝试再次读取相同的输入字符

nextInt方法的行为如下:

  • 获取足以形成令牌的字符
  • 尝试将整个令牌转换为整数(使用基数为10的整数语法)
  • 如果转换成功,则返回转换后的整数
  • 如果转换失败,请将所有字符放回原处,然后抛出异常。

我强烈建议您仔细阅读Scanner课程的javadocs,以便了解您实际使用的方法。

所以...正如你所看到的...如果你在nextInt()电话失败后拨打nextInt(),你就会重复同样的失败。

没有捕到第二个异常的原因是它没有被抛出try { ... }块。

解决方案:您应该调用一个只会丢弃垃圾的方法,而不是在处理程序中调用nextInt()。在这种情况下,最明智的做法是扔掉一切直到下一行的结尾。

提示#1:nextLine()将所有内容都提升到下一个行尾。阅读该方法的javadocs。

提示#2:如果你理解我所说的话,你就会知道在哪里修改。

答案 1 :(得分:-1)

尝试:

choice = Integer.parseInt(sc.nextLine());

你的程序会喜欢这个:

try (Scanner sc = new Scanner(System.in)) {

    sc.useDelimiter("\n");
//    Fixture f = new Fixture();
    boolean inputValid = false;
    int choice = 0;

//    removed outer do..while(); loop

    do {
        System.out.println("\f\t\tFootball Database");
        System.out.println("A utility to help make footballing events easier to manage.");
        System.out.println("");
        System.out.println("\t> Press 1 to manage players ");
        System.out.println("\t> Press 2 to manage teams");
        System.out.println("\t> Press 3 to manage coaches");
        System.out.println("\t> Press 4 to manage fixtures");
        System.out.println("\t> Press 5 to save database to file");
        System.out.println("\t> Press 6 to load database from file");
        System.out.println("\t> Press 7 to terminate program");
        System.out.println("");

        System.out.print("Enter your choice : ");
        try{
//    Always use nextLine() if you mix String and basic Datatype
            choice = Integer.parseInt(sc.nextLine());
            inputValid = true;
        }catch(NumberFormatException e){
            System.out.println("Invalid input");
            inputValid = false;
//    Removed unnecessary two sc.nextInput() lines
        }
    }while(inputValid == false);

    System.out.println("choice is : " + choice);
}