Chu*_*ang 38 java regex class matching fully-qualified-naming
在文本中匹配完全限定的Java类名称的最佳方法是什么?
例如:java.lang.Reflect
,java.util.ArrayList
,org.hibernate.Hibernate
.
Tom*_*lak 70
Java完全限定的类名(假设为"N")具有结构
N.N.N.N
Run Code Online (Sandbox Code Playgroud)
"N"部分必须是Java标识符.Java标识符不能以数字开头,但在初始字符之后,它们可以使用字母和数字,下划线或美元符号的任意组合:
([a-zA-Z_$][a-zA-Z\d_$]*\.)*[a-zA-Z_$][a-zA-Z\d_$]*
------------------------ -----------------------
N N
Run Code Online (Sandbox Code Playgroud)
它们也可以不是保留字(如import
,true
或null
).如果您只想检查合理性,以上就足够了.如果您还想检查有效性,则还必须检查保留字列表.
Java标识符可以包含任何Unicode字母,而不是"仅拉丁语".如果您也想检查这一点,请使用Unicode字符类:
([\p{Letter}_$][\p{Letter}\p{Number}_$]*\.)*[\p{Letter}_$][\p{Letter}\p{Number}_$]*
Run Code Online (Sandbox Code Playgroud)
或者,简而言之
([\p{L}_$][\p{L}\p{N}_$]*\.)*[\p{L}_$][\p{L}\p{N}_$]*
Run Code Online (Sandbox Code Playgroud)
在Java语言规范(第3.8节)有大约有效标识符名称的所有细节.
另请参阅此问题的答案:Java Unicode变量名称
根据@ alan-moore的优秀评论,这是一个完全工作的课程
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.regex.Pattern;
import org.junit.Test;
public class ValidateJavaIdentifier {
private static final String ID_PATTERN = "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";
private static final Pattern FQCN = Pattern.compile(ID_PATTERN + "(\\." + ID_PATTERN + ")*");
public static boolean validateJavaIdentifier(String identifier) {
return FQCN.matcher(identifier).matches();
}
@Test
public void testJavaIdentifier() throws Exception {
assertTrue(validateJavaIdentifier("C"));
assertTrue(validateJavaIdentifier("Cc"));
assertTrue(validateJavaIdentifier("b.C"));
assertTrue(validateJavaIdentifier("b.Cc"));
assertTrue(validateJavaIdentifier("aAa.b.Cc"));
assertTrue(validateJavaIdentifier("a.b.Cc"));
// after the initial character identifiers may use any combination of
// letters and digits, underscores or dollar signs
assertTrue(validateJavaIdentifier("a.b.C_c"));
assertTrue(validateJavaIdentifier("a.b.C$c"));
assertTrue(validateJavaIdentifier("a.b.C9"));
assertFalse("cannot start with a dot", validateJavaIdentifier(".C"));
assertFalse("cannot have two dots following each other",
validateJavaIdentifier("b..C"));
assertFalse("cannot start with a number ",
validateJavaIdentifier("b.9C"));
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
Renaud提供的图案。但是,据我所知,它总是会在最后回溯。
要对其进行优化,您基本上可以将前一半与后一半交换。请注意,您还需要更改点匹配。
以下是我的版本,与原始版本相比,运行速度快大约两倍:
String ID_PATTERN = "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";
Pattern FQCN = Pattern.compile(ID_PATTERN + "(\\." + ID_PATTERN + ")*");
Run Code Online (Sandbox Code Playgroud)
我无法写评论,所以我决定写一个答案。