テキスト内の完全修飾 Java クラス名を照合する最良の方法は何ですか?
例: java.lang.Reflect
、java.util.ArrayList
、org.hibernate.Hibernate
。
テキスト内の完全修飾 Java クラス名を照合する最良の方法は何ですか?
例: java.lang.Reflect
、java.util.ArrayList
、org.hibernate.Hibernate
。
Java の完全修飾クラス名 (「N」としましょう) の構造は次のとおりです。
N.N.N.N
「N」の部分は Java 識別子でなければなりません。Java 識別子は数字で始めることはできませんが、最初の文字の後には、文字と数字、アンダースコア、またはドル記号の任意の組み合わせを使用できます。
([a-zA-Z_$][a-zA-Z\d_$]*\.)*[a-zA-Z_$][a-zA-Z\d_$]*
------------------------ -----------------------
N N
また、予約語 ( import
、true
または などnull
) にすることもできません。妥当性のみをチェックしたい場合は、上記で十分です。有効性も確認したい場合は、予約語のリストも確認する必要があります。
Java 識別子には、「ラテンのみ」の代わりに任意の Unicode 文字を含めることができます。これも確認したい場合は、Unicode 文字クラスを使用します。
([\p{Letter}_$][\p{Letter}\p{Number}_$]*\.)*[\p{Letter}_$][\p{Letter}\p{Number}_$]*
または、略して
([\p{L}_$][\p{L}\p{N}_$]*\.)*[\p{L}_$][\p{L}\p{N}_$]*
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"));
}
}
Renaud によって提供されたパターンは機能しますが、彼の元の答えは常に最後に後戻りします。
それを最適化するために、基本的に前半と後半を入れ替えることができます。ドット マッチも変更する必要があることに注意してください。
以下は私のバージョンで、元のバージョンと比較して約 2 倍の速度で実行されます。
String ID_PATTERN = "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";
Pattern FQCN = Pattern.compile(ID_PATTERN + "(\\." + ID_PATTERN + ")*");
コメントを書くことができないので、代わりに回答を書くことにしました。
私は(自分で)同様の答え(Tomalakの答えとして)、MMMNのようなものにたどり着きました:
([a-z][a-z_0-9]*\.)*[A-Z_]($[A-Z_]|[\w_])*
どこ、
M = ([a-z][a-z_0-9]*\.)*
N = [A-Z_]($[A-Z_]|[\w_])*
ただし、この正規表現は (Tomalak の回答とは異なり)、より多くの仮定を行います。
パッケージ名 (M の部分) は小文字のみで、M の最初の文字は常に小文字で、残りはアンダースコア、小文字、数字を混在させることができます。
クラス名 (N の部分) は常に大文字またはアンダースコアで始まり、残りはアンダースコア、文字、数字を混在させることができます。内部クラスは常にドル記号 ($) で始まり、前述のクラス名の規則に従う必要があります。
注:パターン \w は、文字と数字の XSD パターンです (アンダースコア記号 (_) は含まれません)。
この助けを願っています。
次の式は、私にとっては問題なく機能します。
^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+$
みたいなことを言います([\w]+\.)*[\w]+
しかし、あなたがそれで何をしたいのかをより具体的に知ることができるかもしれません;)