
Java 的 switch 语句不支持正则表达式或字符串模式匹配(如 "s"),且原代码误将整个子字符串传入 switch,导致空格、制表符等空白字符无法被正确识别和跳过。
java 的 `switch` 语句不支持正则表达式或字符串模式匹配(如 `"s"`),且原代码误将整个子字符串传入 `switch`,导致空格、制表符等空白字符无法被正确识别和跳过。
在 Java 中,switch 语句仅支持 常量表达式(如 char、int、String 字面量等),但其行为有严格限制:当使用 String 类型时,switch 会进行 equals() 比较;而若传入的是动态子字符串(如 input.substring(cursor)),不仅性能低,更关键的是——它无法精确匹配单个空白字符(如 ' '、' '、' '),因为 "s" 是正则语法,在 switch 中会被当作普通字符串字面量,而非空白符通配符,因此永远无法命中。
根本问题在于原代码逻辑错位:
- ❌ 错误写法:String input = this._input.substring(this._cursor); → switch(input)
此时 input 是从当前位置到末尾的子串(如 " + 15 * (...)"),而 case " " 等只匹配长度为 1 的字符串,必然失败。 - ❌ case "s" 是无效的:s 在 Java 字符串字面量中需写成 "\s",且 switch 不解析正则,它只是逐字匹配字符串 "\s",而非任意空白字符。
✅ 正确做法是:每次只提取当前游标位置的一个 char,用 char 类型进行 switch 匹配。char 类型天然支持单字符比较,语义清晰、性能高效,且能准确识别空格(' ')、制表符(' ')、换行(' ')等。
以下是修复后的核心逻辑(精简可读版):
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
public List<Token> getTokens() throws Exception {
List<Token> tokens = new ArrayList<>();
while (this._cursor < this._input.length()) {
char c = this._input.charAt(this._cursor); // ✅ 提取单个字符
switch (c) {
case ' ': // 空格
case ' ': // 制表符
case '
': // 换行符
// 忽略空白字符,不生成 token,直接跳过
break;
case '+':
tokens.add(new Token(TokenType.PLUS, "+"));
break;
case '-':
tokens.add(new Token(TokenType.MINUS, "-"));
break;
case '*':
tokens.add(new Token(TokenType.MULTIPLY, "*"));
break;
case '/':
tokens.add(new Token(TokenType.DIVIDE, "/"));
break;
case '(':
tokens.add(new Token(TokenType.HAAKJEOPEN, "("));
break;
case ')':
tokens.add(new Token(TokenType.HAAKJESLUIT, ")"));
break;
default:
if (Character.isDigit(c)) {
// 解析多位数字:持续读取连续数字字符
StringBuilder num = new StringBuilder();
while (_cursor < _input.length() && Character.isDigit(_input.charAt(_cursor))) {
num.append(_input.charAt(_cursor));
_cursor++;
}
tokens.add(new Token(TokenType.NUMERICAL, num.toString()));
_cursor--; // 补回最后多进的一位(因循环末尾有 _cursor++)
} else {
throw new Exception("Expected a valid token at position: " + _cursor);
}
break;
}
_cursor++; // ✅ 统一推进游标(注意:数字分支中已手动控制,故此处需 -- 后再 ++)
}
tokens.add(new Token(TokenType.EOF, "EOF"));
return tokens;
}⚠️ 关键注意事项:
- switch 中的 case 必须使用单引号(' ')表示 char,双引号(" ")表示 String,类型不匹配会导致编译错误;
- 空白字符处理必须放在 switch 开头并 break,否则会穿透到 default 分支引发异常;
- 数字解析块内 this._cursor++ 后需 this._cursor--,是因为外层 while 循环末尾还有一次 this._cursor++,避免跳过下一个有效字符;
- 原代码中冗余的 if (this._cursor < this._input.length() != true) 可简化为 if (this._input == null || this._input.isEmpty()) return tokens;,增强健壮性。
通过将 switch 的操作对象从「动态子字符串」降维到「确定单字符」,既符合 Java 语言规范,又使词法分析逻辑清晰、可维护性强,彻底解决空格与运算符无法识别的问题。

















