hasNextLine() 仅检测缓冲区是否有下一行(含空行),不等价于输入流结束;它会在无输入时阻塞等待,仅在收到Ctrl+D/Ctrl+Z触发EOF后才返回false。

Scanner.hasNextLine() 不能可靠判定“输入流是否已结束”,它只是检查当前 Scanner 缓冲区中是否有**下一行可读取的字符串(含空行)**,而这个缓冲区是否为空,取决于底层输入流(如 System.in)是否已关闭、是否还有未读完的数据,以及用户/系统如何触发输入结束。
为什么 hasNextLine() 不等于“流是否结束”?
原因在于:
-
阻塞等待输入:当控制台输入未关闭且无新数据时,
hasNextLine()会**阻塞等待用户输入**(不是立即返回false),直到用户按下回车(生成一行)或关闭流(如 Ctrl+D / Ctrl+Z); -
空行也算“有下一行”:用户只按回车(输入空行),
hasNextLine()返回true,nextLine()返回空字符串""; -
流未关闭 ≠ 有数据:终端保持打开状态(如命令行窗口没关),但用户长时间不输入,
hasNextLine()就一直卡住,不会超时或返回false。
真正判断“输入结束”的常用方式
标准做法是依赖操作系统信号来关闭 System.in:
-
Linux/macOS:输入完成后按 Ctrl + D(EOF 字符),此时
hasNextLine()立即返回false; -
Windows:按 Ctrl + Z 再按回车,同样触发 EOF,
hasNextLine()返回false; - 注意:必须在**新行开头**按这些组合键(即前一行已回车),否则可能被当作普通输入字符处理。
安全读取控制台行的推荐写法
不要仅靠 hasNextLine() 循环,而应结合明确的退出条件或异常处理:
-
方式一:用 while(hasNextLine()) + 显式终止逻辑
例如约定输入 "quit" 或空行退出:while (scanner.hasNextLine()) {<br> String line = scanner.nextLine();<br> if (line == null || line.trim().isEmpty() || "quit".equalsIgnoreCase(line)) break;<br> // 处理 line<br>} -
方式二:捕获 InputMismatchException 或 NoSuchElementException(不推荐单独用)
更稳妥的是依赖 EOF 信号后hasNextLine()返回false,自然退出循环; -
方式三:重定向输入(测试/脚本场景)
运行时用java Main ,文件末尾即为 EOF,<code>hasNextLine()读完自动返回false。
小结:关键点记牢
-
hasNextLine()是“有没有下一行可读”,不是“流是不是关了”; - 它在无输入时会阻塞,不会主动返回
false; - 只有收到操作系统级 EOF(Ctrl+D / Ctrl+Z)后,它才返回
false; - 日常开发中,应配合语义化退出条件(如特定命令、空行)或确保用户知道如何发送 EOF。










