nextLine()为什么“跳过”了?——一场关于Scanner缓冲区状态的深度对话
你有没有遇到过这样的场景:
用户刚输入完年龄,回车一按,程序就“跳过”了姓名输入,直接打印出一个空名字?
控制台输出像这样:
请输入年龄: 25 请输入姓名: 年龄=25, 姓名=''不是代码写错了,不是 IDE 抽风,也不是 JVM bug。
这是Scanner在认真执行它的契约——只是这个契约,藏在了缓冲区指针悄悄停下的那个换行符后面。
它不是 Bug,是设计在呼吸
Scanner不是黑盒,它是一台精密但透明的解析引擎。它的核心不是“读取”,而是基于分隔符的 Token 提取 + 缓冲区游标管理。
我们常误以为nextInt()是“读完数字并吞掉回车”,其实它只做两件事:
- 跳过开头所有空白(包括空格、制表符、换行符);
- 解析连续数字字符,直到遇到下一个分隔符(比如\n)——然后停下,把那个\n留在缓冲区里,原封不动。
而nextLine()的定义非常干净:
“从当前位置开始,读到下一个换行符为止,并消费它。”
所以当nextInt()把游标停在\n前,nextLine()就立刻看到它、吃掉它、返回空字符串——逻辑满分,行为确定,毫无意外。
这不是缺陷,是职责清晰的体现:
✅nextInt()只负责“解析数字”;
✅nextLine()只负责“读一行并清掉换行符”;
❌ 它们都不该越界替对方擦屁股——但你得知道谁该擦,什么时候擦。
看得见的缓冲区:一次手动画图级理解
假设用户输入的是:
25↵ Zhang San↵(其中↵表示回车符\n)
Scanner内部缓冲区实际接收的是字符流:
['2', '5', '\n', 'Z', 'h', 'a', 'n', 'g',