正则表达式匹配完全限定的类名

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,truenull).如果您只想检查合理性,以上就足够了.如果您还想检查有效性,则还必须检查保留字列表.

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变量名称

  • 实际上,这些方法已经由特殊字符类表示.我们需要匹配Java标识符的是""(\\ p {javaJavaIdentifierStart} \\ p {javaJavaIdentifierPart}*\\.)+ \\ p {javaJavaIdentifierStart} \\ p {javaJavaIdentifierPart}*"`.优雅,你的名字是Java! (32认同)
  • Java标识符可以以任何货币符号开头,因此$ val,£val和¥val都是有效的.我认为这适用于类和变量.请参阅java api http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Character.html#isJavaIdentifierStart(char) (2认同)

Ren*_*aud 7

根据@ 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)

我无法写评论,所以我决定写一个答案。