next()和nextLine()混用导致首行被跳过,因next类方法不消费换行符而nextLine()立即读取残留换行符;应统一用nextLine()后转换类型,或在nextXXX()后加nextLine()清缓存。

next() 和 nextLine() 为什么总吃掉第一行输入
根本原因是 next()、nextInt() 等方法不消费换行符,而 nextLine() 会立刻读取当前缓冲区里剩下的换行符,导致“跳过”下一行。
典型现象:先调 nextInt() 读数字,再调 nextLine() 读名字,结果名字直接为空。
- 解决办法:在
nextInt()后加一句scanner.nextLine()清掉残留换行符 - 更稳妥的写法是统一用
nextLine(),再手动转类型,比如Integer.parseInt(scanner.nextLine()) - 别混用
nextXXX()和nextLine()—— 这是 80% 的控制台输入 bug 来源
nextDouble() / nextInt() 抛 InputMismatchException 怎么办
这不是代码写错了,而是用户输的内容和期待类型不匹配,比如用 nextInt() 却输入了 abc 或 3.14,Scanner 不会跳过错误输入,下次调用仍会卡在原地重试。
- 必须用
hasNextInt()/hasNextDouble()预检,而不是靠 try-catch 挡着 - 一旦
hasNextXxx()返回false,得调scanner.next()把非法 token 吃掉,否则循环会死锁 - 示例片段:
while (!scanner.hasNextInt()) {<br> System.out.print("请输入整数:");<br> scanner.next(); // 吃掉非整数token<br>}<br>int n = scanner.nextInt();
Scanner 能不能安全用于多线程或频繁创建
不能。Scanner 不是线程安全的,同时被两个线程调 next() 会出不可预测行为;而且它内部包装了 System.in,每次 new Scanner(System.in) 并不会新开流,只是共享底层字节流,但多个 Scanner 实例会互相干扰缓冲区状态。
立即学习“Java免费学习笔记(深入)”;
- 一个进程只该有一个 Scanner 实例,通常声明为 static 成员或单例传入
- 别在循环里反复
new Scanner(System.in),这不仅低效,还可能让后续读取失败 - 如果真要隔离输入逻辑,用
new Scanner(new ByteArrayInputStream(inputBytes))做单元测试,而非碰System.in
用 Scanner 读文件时中文乱码怎么处理
默认编码是平台默认 Charset(Windows 是 GBK,macOS/Linux 通常是 UTF-8),但文件很可能存的是 UTF-8,没显式指定就会解码错。
- 构造 Scanner 时必须指定编码:
new Scanner(new File("data.txt"), "UTF-8") - 别依赖
Scanner.getEncoding()查看——它返回的是实际检测到的编码,不是你期望的,且不一定准 - 如果文件路径含中文,
new File("中文.txt")在 Windows 上一般没问题,但跨平台部署时建议用Paths.get(...).toFile()避免路径解析歧义










