Java 的有效标识符是:
- 至少有一个字符
- 第一个字符必须是字母
[a-zA-Z]、下划线_或美元符号$
- 其余字符可以是字母、数字、下划线或美元符号
- 不得将保留字用作标识符
-
更新:单下划线
_ 是关键字since Java 9
验证前三个条件的简单正则表达式如下:(\b([A-Za-z_$][$\w]*)\b),但它不会过滤掉保留字。
要排除保留字,需要负前瞻(?!) 来指定一组无法匹配的标记:
\b(?!(_\b|if|else|for|float|int))([A-Za-z_$][$\w]*):
- 第 1 组:
(?!(_\b|if|else|for|float|int)) 排除指定单词的列表
- 第 2 组:
([A-Za-z_$][$\w]*) 匹配标识符。
但是,单词边框\b 会消耗美元符号$,因此此正则表达式无法匹配以$ 开头的标识。
此外,我们可能希望排除字符串和字符文字内部的匹配(“not_a_variable”、“c”、“\u65”)。
这可以通过使用正向lookbehind (?<=)来匹配组before主表达式来完成,而不是将其包含在结果中而不是word-border类\b:
(?<=[^$\w'"\\])(?!(_\b|if|else|for|float|int))([A-Za-z_$][$\w]*)
Online demo for a short list of reserved words
接下来,Java保留字的完整列表如下,可以收集成一个单独的以|分隔的标记字符串。
下面提供了一个测试类,展示了正则表达式的最终模式及其用于检测 Java 标识符的用法。
import java.util.Arrays;
import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
public class IdFinder {
static final List<String> RESERVED = Arrays.asList(
"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const",
"continue", "default", "double", "do", "else", "enum", "extends", "false", "final", "finally",
"float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long",
"native", "new", "null", "package", "private", "protected", "public", "return", "short", "static",
"strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try",
"void", "volatile", "while", "_\\b"
);
static final String JAVA_KEYWORDS = String.join("|", RESERVED);
static final Pattern VALID_IDENTIFIERS = Pattern.compile(
"(?<=[^$\\w'\"\\\\])(?!(" + JAVA_KEYWORDS + "))([A-Za-z_$][$\\w]*)");
public static void main(String[] args) {
System.out.println("ID pattern:\n" + VALID_IDENTIFIERS.pattern());
String code = "public class Main {\n\tstatic int $1;\n\tprotected char _c0 = '\\u65';\n\tprivate long c1__$$;\n}";
System.out.println("\nIdentifiers in the following code:\n=====\n" + code + "\n=====");
VALID_IDENTIFIERS.matcher(code).results()
.map(MatchResult::group)
.forEach(System.out::println);
}
}
输出
ID pattern:
(?<=[^$\w'"\\])(?!(abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|double|do|else|enum|extends|false|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|null|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|transient|true|try|void|volatile|while|_\b))([A-Za-z_$][$\w]*)
Identifiers in the following code:
=====
public class Main {
static int $1;
protected char _c0 = '\u65';
private long c1__$$;
}
=====
Main
$1
_c0
c1__$$