Java while循环输入quit退出时nextLine与nextInt输入异常排查
Scanner输入逻辑异常问题排查
问题描述
程序需求为循环接收用户依次输入的字符串、整数,拼接内容输出固定句式Eating {整数} {字符串} a day keeps you happy and healthy.,直到用户输入字符串quit时终止。
初始版本代码因Scanner方法使用逻辑错误抛出异常,异常栈信息如下:
Exception in thread "main" java.util.InputMismatchException at java.base/java.util.Scanner.throwFor(Scanner.java:939) at java.base/java.util.Scanner.next(Scanner.java:1594) at java.base/java.util.Scanner.nextInt(Scanner.java:2258) at java.base/java.util.Scanner.nextInt(Scanner.java:2212) at LabProgram.main(LabProgram.java:8)
初始错误代码
import java.util.Scanner; public class LabProgram { public static void main(String[] args) { Scanner in = new Scanner(System.in); String inputStr = in.nextLine(); int inputInt = in.nextInt(); while(!inputStr.equals("quit")){ System.out.println("Eating " + inputInt + " " + inputStr + " a day keeps you happy and healthy."); } } }
调整代码后程序可正常输出,但开发者发现新增的in.nextLine()行看似会抛出异常,程序却依然能正常运行,存疑代码如下:
String inputStr = ""; int inputInt; while(!inputStr.equals("quit")){ inputStr = in.next(); inputInt = in.nextInt(); in.nextLine(); // 该行看似会抛异常,但程序仍能正常输出 System.out.println("Eating " + inputInt + " " + inputStr + " a day keeps you happy and healthy."); }
根因分析
所有问题的核心是对Scanner的输入消费规则理解不到位,先明确两个核心规则:
next()、nextInt()这类以空白符(空格、换行、制表符)作为分隔符的读取方法,只会读取分隔符之前的有效内容,不会消费分隔符本身。也就是说用户输入整数后按下的回车换行符,会一直残留在输入缓冲区中。nextLine()方法会读取从当前缓冲区指针位置到最近一个换行符的所有内容,同时会消费掉这个换行符,将指针移到下一行开头。
- 初始代码报错原因
初始版本有两个明显逻辑错误:- 循环内部没有重新读取
inputStr和inputInt的值,只要第一次输入的字符串不是quit,程序就会死循环重复输出同一句话。 - 没有做退出前置判断:如果第一次输入的字符串是
quit,程序依然会执行nextInt()要求用户输入整数,若此时输入非数字内容,就会直接抛出InputMismatchException。
- 循环内部没有重新读取
- 对
in.nextLine()行的异常误解
这行代码的作用就是消费nextInt()读取整数后残留在缓冲区的换行符,避免下一轮循环读取字符串时读到空内容。
正常输入流程下,缓冲区必然存在这个残留换行符,nextLine()此时只会读取到一个空字符串,完全不会抛出异常。你观察到的异常全部来自它前面的nextInt()调用:比如本该输入整数的位置输入了非数字内容,nextInt()会直接抛出异常,程序根本执行不到后面的in.nextLine()行,所谓“这行抛异常但程序正常运行”完全是错觉。 - 调整后代码的隐藏问题
目前的退出逻辑存在缺陷:用户输入quit后,程序依然会停在nextInt()步骤要求输入一个整数,输入完成后才会触发退出判断,不符合需求。正确逻辑应该是读取字符串后先判断是否为quit,如果是就直接终止循环,不需要再读取后续整数。
修正后可直接运行的代码
import java.util.Scanner; public class LabProgram { public static void main(String[] args) { Scanner in = new Scanner(System.in); while (true) { String inputStr = in.next(); if (inputStr.equals("quit")) { break; } int inputInt = in.nextInt(); // 消费整数后残留的换行符 in.nextLine(); System.out.println("Eating " + inputInt + " " + inputStr + " a day keeps you happy and healthy."); } in.close(); } }
内容的提问来源于stack exchange,提问作者Brian Miller
相关产品推荐
相关产品推荐

