Scanner.hasNext(Pattern)用于试探性匹配下一个完整token是否符合指定正则,不消耗输入,常用于安全跳过非法输入或条件读取。

Scanner.hasNext(Pattern) 的作用不是“预校验”,而是“试探性匹配”——它不消耗输入,只判断**下一个完整的令牌(token)是否能匹配指定正则模式**,常用于安全跳过非法输入或条件读取。
理解 hasNext(Pattern) 的行为边界
它基于 Scanner 默认的分隔符(通常是空白符)将输入切分为 token,然后对下一个未被消费的 token 整体尝试匹配正则。注意三点:
- 匹配的是整个 token,不是子串(例如 pattern 是
"\d+",输入"123abc"不会匹配,因为整个 token 是"123abc") - 不改变输入位置,调用后仍可安全调用
next()或nextInt()等获取该 token - 若当前无更多 token(已到流末尾),返回
false,不会抛异常
典型使用场景与写法
常见于交互式输入中,避免因格式错误导致 InputMismatchException 或阻塞:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
-
等待合法整数输入:
while (!scanner.hasNext("\d+")) { scanner.next(); System.out.print("请输入有效数字:"); }
意思是:只要下一个 token 不是纯数字,就跳过它(next()消耗掉非法 token),再提示重输。 -
选择性读取邮箱或手机号:
if (scanner.hasNext("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")) { String email = scanner.next(); } -
区分命令类型(如 "quit"、"load file.txt"、"save /path"):
if (scanner.hasNext("(?i)quit|exit")) { ... } else if (scanner.hasNext("(?i)load\s+\S+")) { ... }
和 hasNextXXX() 方法的关键区别
hasNextInt()、hasNextDouble() 等内部也用正则,但它们:
立即学习“Java免费学习笔记(深入)”;
- 隐式绑定类型规则(如
hasNextInt()等价于hasNext("\d+")仅当无符号;实际支持负号、进制前缀等更复杂逻辑) - 不能自定义模式,而
hasNext(Pattern)完全自由,适合业务语义校验(如日期"\d{4}-\d{2}-\d{2}"、IP"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") - 注意:IP 这类需额外逻辑验证范围(如每段 ≤255),
hasNext只管字符串形式
实用建议与避坑
- 正则尽量锚定开头结尾(如用
"^\d+$"而非"\d+"),避免误匹配("123abc"中"123"会被"\d+"匹配成功,但hasNext是对整个 token 判定,所以其实无需^$—— 因为 token 本身就是独立单元) - 若需匹配含空格的多词内容(如完整一行),先用
useDelimiter("\n")改分隔符,再hasNext("your-pattern") - 不要用它替代输入清洗:它不修改数据,只是“看一眼”。真正校验应在
next()后做二次解析(如LocalDate.parse(...))

















