
本文讲解如何正确使用 scanner 在单行输入中逐词读取并自然终止循环,避免无限等待;核心方案是先用 nextline() 获取整行,再用新 scanner 解析该行,从而以 hasnext() 安全控制循环退出。
本文讲解如何正确使用 scanner 在单行输入中逐词读取并自然终止循环,避免无限等待;核心方案是先用 nextline() 获取整行,再用新 scanner 解析该行,从而以 hasnext() 安全控制循环退出。
在 Java 中,若希望从标准输入读取一行文本,并按单词(空格分隔)逐个处理,且在用户按下 Enter 后自动结束输入循环,直接在 while(true) 中混合调用 sc.next() 和 sc.hasNext() 会导致逻辑错误——因为 sc.next() 本身会阻塞等待输入,而 sc.hasNext() 在已调用 next() 后才检查,无法作为及时退出依据。
✅ 正确做法是:分两层扫描
- 使用一个
Scanner(如scl)调用nextLine()一次性读取整行(遇到 Enter 即返回),确保输入终止可控; - 将该行字符串构造为新的
Scanner(如sc = new Scanner(scl.nextLine())),在其上安全使用hasNext()+next()组合遍历单词。
以下是优化后的完整示例代码:
import edu.princeton.cs.algs4.StdRandom;
import java.util.Scanner;
public class RandomWord {
public static void main(String[] args) {
String x = null, winner = null;
final Scanner scl = new Scanner(System.in); // 用于读取整行
int i = 1;
// 关键:先获取一行,再构建内存 Scanner
final Scanner sc = new Scanner(scl.nextLine());
while (sc.hasNext()) { // 安全判断——仅针对已加载的行
x = sc.next();
System.out.println("读取单词: " + x);
// 执行你的业务逻辑(如随机抽样)
if (StdRandom.bernoulli(1.0 / i)) {
winner = x;
}
i++;
}
// 必须关闭两个 Scanner
sc.close();
scl.close();
System.out.println("最终胜出单词: " + winner);
}
}⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- ❌ 避免在同一个
Scanner上交替调用next()和hasNext()作为循环条件——这会导致阻塞或跳过首个 token; - ✅
nextLine()是唯一能响应 Enter 键并立即返回的阻塞方法,它是实现“按行提交”的关键; - ? 记得关闭两个
Scanner实例(sc和scl),防止资源泄漏; - ? 若需支持多行输入(每行独立处理),可将内层 Scanner 逻辑封装为方法,并在外层
while(scl.hasNextLine())中循环调用。
该方案简洁、健壮,完全符合命令行交互直觉:用户输入一整行 → 按 Enter → 程序立即解析并退出单词循环。


















