Java中InputMismatchException失效,是否需改用Scanner替代DataInputStream?
首先明确回答你的问题:是的,使用Scanner确实能让你正常捕获InputMismatchException,不过我们先搞清楚当前代码出问题的根源,再给出两种可行的解决方案。
为什么当前代码捕获不到InputMismatchException?
你现在的写法里,DataInputStream.readLine()只是单纯读取控制台输入的字符串,它不会做任何类型校验,自然也不会抛出InputMismatchException——这个异常是Scanner类的专属异常,专门用于表示输入的数据类型和预期不匹配的场景。
真正抛出NumberFormatException的是Integer.parseInt()方法:当你传入像"1.2"这样的非整数字符串时,它无法将其解析为整数,就会抛出这个异常,而你的catch块写的是捕获InputMismatchException,根本抓不到这个异常,所以程序直接崩溃了。
解决方案1:改用Scanner(推荐)
用Scanner的nextInt()方法时,它会自动校验输入是否为整数,如果输入不符合要求(比如输入1.2),就会直接抛出InputMismatchException,正好匹配你想要捕获的异常类型。而且Scanner的API更适合处理控制台的交互式输入,代码逻辑也更清晰:
import java.util.Scanner; import java.util.InputMismatchException; public class NChooseR { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int numChosenObj = -1; int numTotalObj = -1; // 处理第一个输入的异常与循环输入 while (true) { try { System.out.print("Enter the number of objects to choose: "); numChosenObj = scanner.nextInt(); break; // 输入正确,跳出循环 } catch (InputMismatchException e) { System.out.println("You must input an integer value."); scanner.nextLine(); // 清空输入缓冲区的无效内容,避免死循环 } } // 处理第二个输入的异常与循环输入 while (true) { try { System.out.print("Enter the total number of objects to choose from: "); numTotalObj = scanner.nextInt(); break; } catch (InputMismatchException e) { System.out.println("You must input an integer value."); scanner.nextLine(); } } int difference = numTotalObj - numChosenObj; int rFact = factorial(numChosenObj); int nFact = factorial(numTotalObj); int differenceFact = factorial(difference); int totalWaysToChoose = nFact / (rFact * differenceFact); System.out.println(); System.out.println("There are " + totalWaysToChoose + " ways to choose " + numChosenObj + " objects from " + numTotalObj + " total number of objects."); scanner.close(); } // 阶乘计算方法示例 private static int factorial(int n) { int result = 1; for (int i = 2; i <= n; i++) { result *= i; } return result; } }
这里加了while循环和scanner.nextLine()是关键:当输入错误时,必须清空缓冲区里的无效输入,否则nextInt()会一直读取同一个错误的输入,导致程序陷入无限循环。
解决方案2:不换DataInputStream,修改异常捕获
如果你不想改用Scanner,只需要把catch块的异常类型改成NumberFormatException,就能捕获输入非整数的情况了:
import java.io.DataInputStream; import java.io.IOException; public class NChooseR { public static void main(String[] args) throws IOException { DataInputStream input = new DataInputStream(System.in); int numChosenObj = -1; int numTotalObj = -1; try { System.out.print("Enter the number of objects to choose: "); numChosenObj = Integer.parseInt(input.readLine()); } catch (NumberFormatException e) { // 修改为捕获NumberFormatException System.out.println("You must input an integer value."); // 这里可以添加逻辑让用户重新输入,否则后续计算会因非法值出错 } try { System.out.print("Enter the total number of objects to choose from: "); numTotalObj = Integer.parseInt(input.readLine()); } catch (NumberFormatException e) { // 同样修改异常类型 System.out.println("You must input an integer value."); } // 后续计算逻辑... input.close(); } // 阶乘计算方法... private static int factorial(int n) { int result = 1; for (int i = 2; i <= n; i++) { result *= i; } return result; } }
不过这种写法需要你自己手动实现重新输入的逻辑,整体便利性不如Scanner方案。
内容的提问来源于stack exchange,提问作者gino

