Scanner的nextLine()阻塞常因前序nextInt()等未消耗换行符,导致其立即读取残留 ;应在其后加nextLine()清空缓冲区,并用trim()或isBlank()校验空输入,避免close()关闭System.in。

Java Scanner 读取输入时阻塞在 nextLine() 的原因
用 while 循环配合 Scanner 等待用户输入直到满足条件,最常卡在 nextLine() 不返回——不是代码写错了,而是前一个 nextInt()、nextDouble() 之类的方法没吃掉换行符,导致 nextLine() 立刻读到残留的
,看似“跳过”了输入。
常见错误现象:请输入数字: 提示后直接打印下一条提示,没给用户敲回车的机会。
- 使用场景:需要先读一个整数再读一行字符串(比如菜单选项+备注)
- 解决方法:在
nextInt()后加一句scanner.nextLine();清空缓冲区 - 不推荐用
next()替代nextLine()——它只读到空格,无法处理含空格的输入
while 循环里怎么安全判断输入是否符合预期
不能只靠 hasNextLine() 或 hasNextInt() 做循环条件,它们只检查“有没有”,不保证“能用”。比如用户输了个字母,hasNextInt() 返回 false,但后续调用 nextInt() 会抛 InputMismatchException。
正确做法是先用 hasNextXXX() 探路,再用对应方法读取;或者统一用 nextLine() 读字符串,再手动解析。
立即学习“Java免费学习笔记(深入)”;
- 推荐写法:
while (!(line = scanner.nextLine()).trim().equals("quit")) { ... } - 数字校验别偷懒:
if (line.matches("\d+")) { num = Integer.parseInt(line); },避免NumberFormatException - 注意
trim():用户可能多敲空格,不清理会导致" 5 " != "5"
为什么 Scanner 在循环外 close() 会出问题
Scanner 关闭时会连带关闭它包装的底层流(比如 System.in)。一旦关了,后续任何对 System.in 的读取(包括新创建的 Scanner)都会抛 IllegalStateException: Scanner closed。
这在 while 循环里尤其隐蔽:你可能在某次输入后写了 scanner.close(),后面循环又试图读——报错位置和实际关闭点隔得很远。
- 原则:只要还在读
System.in,就别关Scanner - 如果必须提前退出,用
break,不要close() - 真要释放资源?等整个程序结束,JVM 自动回收
System.in
输入为空或只含空白字符时的典型误判
用户直接按回车,nextLine() 返回空字符串 "",不是 null。很多人写 while (line != null) 或 if (line.length() > 0),结果空输入被当成有效数据往下走。
更稳妥的判断是结合 trim() 和长度,或者用 isBlank()(Java 11+)。
- 兼容老版本:
line == null || line.trim().isEmpty() - Java 11+ 更简洁:
line == null || line.isBlank() - 别用
line.equals(""):万一line是null,直接 NPE - 如果业务允许空输入(比如可选备注),那就明确区分逻辑,别混在“退出条件”里
边界情况比想象中多:换行符残留、空字符串、流提前关闭、类型匹配失败……这些都不是语法错误,编译全过,但一跑就卡或崩。写的时候多想半秒输入可能长什么样,比事后查堆栈快得多。


















