2012-12-20 17 views
9

Czy istnieje metoda w języku Java, aby sprawdzić, czy łańcuch może być używany jako nazwa klasy?Jak sprawdzić, czy nazwa klasy jest poprawna?

+0

możliwe duplikat [wyrażenie regularne pasujące pełni wykwalifikowanych klas Java] (http://stackoverflow.com/questions/5205339/regular-expression-matching-fully-qualified-java-classes) –

+1

Pyta, czy nazwa ma być prawną nazwą, a nie czy klasa faktycznie istnieje. (Myślę) – dashrb

+0

tak chcę utworzyć nową klasę z odbiciem i nazwą ... więc muszę sprawdzić, czy nazwa jest poprawna – Maxii

Odpowiedz

0

Yap -

Class.forName(String className); 

Zwraca obiekt klasy powiązanych z klasy lub interfejsu z danej nazwy strun. i rzuca Exceptions

LinkageError - if the linkage fails 
ExceptionInInitializerError - if the initialization provoked by this method fails 
ClassNotFoundException - if the class cannot be located 
+1

Sprawdza, czy klasa istnieje, a nie czy ciąg jest zgodny z prawem do użycia jako nazwa klasy (o czym OP chce wiedzieć). –

+0

@ Ted Właśnie podałem informacje i myślę, że byłoby wystarczająco dużo informacji, aby funkcja taka jak sugerował MrLore. –

+0

Nie mogę się zgodzić. OP chce wiedzieć, czy nazwa będzie ważna jako nazwa klasy, a nie czy klasa istnieje. Problem z twoją sugestią jest taki, że rzuci ten sam "ClassNotFoundException" dla legalnych nazw, takich jak "foo.bar" (jeśli klasa nie istnieje) i dla nielegalnych nazw takich jak '"! =? "'. –

6

Po prostu metodą Class.forName(String name), które mogą być używane do testowania to w następujący sposób:

public static boolean classExists(String className) 
{ 
    try 
    { 
     Class.forName(className); 
     return true; 
    } 
    catch(ClassNotFoundException ex) 
    { 
     return false; 
    } 
} 

EDIT: Jeśli, jak dashrb mówi, prosisz dla sposób, aby określić, czy String może być użyty jako nazwa klasy (a nie wtedy, gdy już istnieje klasa o tej nazwie), wtedy potrzebna jest kombinacja metody, którą napisałem powyżej (z odwróconymi bajtami, jak możesz " t ponownego użycia nazw klas) oraz w połączeniu z sprawdzeniem, czy ciąg jest słowem kluczowym zarezerwowanym dla środowiska Java. Ostatnio miałem podobny problem i stworzyłem dla niego klasę narzędziową, którą można znaleźć here. Nie napiszę tego dla ciebie, ale po prostu musisz dodać czek na !JavaKeywords.isKeyword(className).

Edit 2: I oczywiście, jeśli chcesz również egzekwować ogólnie przyjętych standardów kodowania, można po prostu upewnij się, że nazwa klasy rozpoczyna się wielką literą z:

return Character.isUpperCase(className.charAt(0)); 

edit 3: Jak wskazuje Ted Hopp, nawet zawierające słowo kluczowe java unieważnia nazwę klasy, a ponieważ Java-Słowa kluczowe jest używane w jednej z moich aplikacji produkcyjnych, stworzyłem updated version, który zawiera metodę containsKeyword(String toCheck), która również sprawdzi tę ewentualność. Metoda jest następująca (należy pamiętać trzeba listę słów kluczowych w klasie też):

public static boolean containsKeyword(String toCheck) 
{ 
    toCheck = toCheck.toLowerCase(); 
    for(String keyword : keywords) 
    { 
     if(toCheck.equals(keyword) || toCheck.endsWith("." + keyword) || 
      toCheck.startsWith(keyword + ".") || toCheck.contains("." + keyword + ".")) 
     { 
      return true; 
     }//End if 
    }//End for 
    return false; 
}//End containsKeyword() 
+0

Twój wpis edycji jest potrzebną odpowiedzią. Dziękuję Ci! – Maxii

+0

Nie musisz mieć pierwszej litery, aby być kapitałem. – tcb

+0

@ tcb Wiem, ale normalną praktyką jest, że klasy zaczynają się od dużej litery, co do której jestem pewien, że każda klasa nie-prymitywna w wbudowanych pakietach działa. – MrLore

5

użyłem listę słów kluczowych java uprzejmie oferowanych przez MrLore.

private static final Set<String> javaKeywords = new HashSet<String>(Arrays.asList(
    "abstract",  "assert",  "boolean",  "break",   "byte", 
    "case",   "catch",   "char",   "class",   "const", 
    "continue",  "default",  "do",   "double",   "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" 
)); 

private static final Pattern JAVA_CLASS_NAME_PART_PATTERN = 
    Pattern.compile("[A-Za-z_$]+[a-zA-Z0-9_$]*"); 

public static boolean isJavaClassName(String text) { 
    for (String part : text.split("\\.")) { 
     if (javaKeywords.contains(part) || 
       !JAVA_CLASS_NAME_PART_PATTERN.matcher(part).matches()) { 
      return false; 
     }   
    } 
    return text.length() > 0; 
} 
+1

To nie będzie działać poprawnie z takimi nazwami jak "com.example.true" (co jest niedozwoloną nazwą, ponieważ jeden _komponent_ nazwy jest słowem kluczowym) .Zauważ, że test musi również zezwalać na takie nazwy, jak "com.example". .true_fact "'. –

+0

@ Ted Hopp naprawiony, dziękuję – tcb

+1

Nie do końca poprawiony, nadal będzie pozwalał na nazwy takie jak "com.example.true" '. –

14

SourceVersion.isName może być używany do sprawdzania w pełni kwalifikowanych nazw.

Jeżeli nie . s powinno być dozwolone, kontrola może być wykonane w ten sposób:

boolean isValidName (String className) { 
    return SourceVersion.isIdentifier(className) && !SourceVersion.isKeyword(className); 
} 
+0

Spóźniłeś się trzy lata impreza, ale to jest właśnie droga. – mwoodman

Powiązane problemy