
本文详解如何用java正则表达式严格校验用户输入:必须恰好包含6个0–99之间的整数,数字间由一个或多个空格分隔,且字符串首尾不得有空格。
在Java中使用String.matches()进行输入校验时,关键要理解两点:该方法默认锚定整个字符串(即隐含 ^ 和 $),且正则逻辑需覆盖所有非法情形并避免误判。原代码中的两个核心问题在于:
首尾空格检测逻辑错误:^(?!\\s)\\d{1,2}( \\d{1,2})*(?!\\s)$ 中的负向先行断言 (?!\\s) 无法正确约束结尾——它只检查当前位置后是否非空格,但不保证结尾就是数字;更严重的是,* 允许匹配0次,导致单个数字也满足,失去“6个数”的约束。
范围与格式混检失效:^(\\d{1,2} ){5}\\d{1,2}$ 虽能匹配6个0–99的数,但仅支持单个空格分隔;若用户输入 "12 34 56 78 90 99"(含多个空格),此正则失败,却错误触发“数字越界”提示,掩盖了真实问题。
✅ 正确方案应分步、独立、精准校验:
-
第一步:排除空输入
if (numbers == null || numbers.trim().isEmpty()) { return "Error: Input cannot be empty"; } -
第二步:严格验证格式(6个0–99数 + 多空格分隔 + 无首尾空格)
使用单一正则:if (!numbers.matches("^\\d{1,2}(\\s+\\d{1,2}){5}$")) { return "Error: Input must contain exactly 6 numbers (0–99), separated by one or more spaces, with no leading/trailing spaces"; }✅ 解析:
- ^\\d{1,2}:开头必须是1–2位数字(即0–99)
- (\\s+\\d{1,2}){5}:重复5次“一个及以上空格 + 1–2位数字” → 总计6个数字
- $:确保字符串在此结束,杜绝尾部空格
第三步(可选增强):运行时数值校验(防恶意构造如"00"、"01"等,但题目要求0–99,故合法)
实际上,\\d{1,2} 已覆盖0–99(包括"0"、"5"、"99"),无需额外解析校验。但若需绝对严谨(例如排除"00"作为数字),可在split()后对每个Integer.parseInt()结果做范围判断。
? 完整修复后的 validateInput 方法:
public String validateInput(String numbers) {
// 空输入检查(使用 trim() 更鲁棒)
if (numbers == null || numbers.trim().isEmpty()) {
return "Error: Input cannot be empty";
}
// 格式与范围一次性校验:6个0–99数字,多空格分隔,无首尾空格
if (!numbers.matches("^\\d{1,2}(\\s+\\d{1,2}){5}$")) {
return "Error: Input must contain exactly 6 numbers (0–99), separated by one or more spaces, with no leading or trailing spaces";
}
// 可选:进一步验证每个数字是否 ≤99(虽正则已保证,但双重保险)
String[] parts = numbers.split("\\s+");
for (String part : parts) {
int num = Integer.parseInt(part);
if (num < 0 || num > 99) {
return "Error: All numbers must be between 0 and 99 inclusive";
}
}
return ""; // 校验通过
}⚠️ 注意事项:
- 避免在正则中混用 \s 和字面空格(如 " ")——统一用 \\s+ 支持制表符、换行等广义空白(题目要求“1 or more spaces”,但实际建议兼容性更强)。
- 原代码中 computeSum 的 split("\\s+") 是正确的,与正则 \\s+ 保持一致。
- 不要依赖负向断言 (?!...) 处理首尾空格,直接用 ^ 和 $ 锚定 + 显式结构定义更清晰可靠。
通过以上设计,校验逻辑清晰分离、无歧义,每个错误消息都精准对应唯一违规类型,完全满足作业需求。










