10

Is there a method in Java to check if a string can be used as a class name?

Sam
  • 6,961
  • 15
  • 44
  • 63
Maxii
  • 637
  • 2
  • 13
  • 25
  • possible duplicate of [regular expression matching fully qualified java classes](http://stackoverflow.com/questions/5205339/regular-expression-matching-fully-qualified-java-classes) – jmj Dec 20 '12 at 19:31
  • 1
    He's asking if the name would be a legal name, not if the class actually exists. (I think) – dashrb Dec 20 '12 at 19:33
  • yes i want to create a new class with reflection and the name... so i have to check if the name is valid – Maxii Dec 20 '12 at 19:36
  • then it sounds like you do want to know if the string refers to a valid class. See answers below. I thought you were checking for whether the name follows the rules of how classes are allowed to be named. – dashrb Dec 20 '12 at 19:37
  • Sorry.. first i create a new java file and then i create a new object with reflection... so you are right, with your first post – Maxii Dec 20 '12 at 19:43
  • 2
    This is not a duplicate of http://stackoverflow.com/questions/5205339/regular-expression-matching-fully-qualified-java-classes as the poster doesn't care if the solution is regular expression or not – Steve Kuo Dec 20 '12 at 20:47

4 Answers4

24

SourceVersion.isName can be used to check fully qualified names.

If no .s should be allowed, the check can be done this way:

boolean isValidName (String className) {
    return SourceVersion.isIdentifier(className) && !SourceVersion.isKeyword(className);
}
fabian
  • 67,623
  • 12
  • 74
  • 102
6

Quite simply, with the Class.forName(String name) method, which can be used to test this as follows:

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

Edit: If, as dashrb said, you're asking for a way to determine if a String can be used as a class name (rather than if there already is a class by that name), then what you need is a combination of the method I posted above (with the booleans flipped, as you can't reuse class names), and in combination with a check to see if the String is a Java-reserved keyword. I had a similar problem recently and made a utility class for it which you can find here. I won't write it for you, but you basically just need to add in a check for !JavaKeywords.isKeyword(className).

Edit 2: And of course, if you want to also enforce generally accepted coding standards, you could just make sure that the class name starts with a capital letter with:

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

Edit 3: As Ted Hopp points out, even containing a java keyword invalidates a class name, and as JavaKeywords is used in one of my production applications, I have made an updated version which includes the method containsKeyword(String toCheck) which will also check for this eventuality. The method is as follows (please note you need the list of keywords in the class too):

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()
MrLore
  • 3,654
  • 2
  • 24
  • 36
  • You don't need to have you first letter to be capital. – tcb Dec 20 '12 at 19:45
  • @tcb I know, but it's fairly standard practise to have classes start with a capital letter, which I'm fairly sure every non-primitive class in the built-in packages does. – MrLore Dec 20 '12 at 19:48
  • 1
    This deals only with simple names. But a qualified name like `com.example.Foo` is a legal class name. – Ted Hopp Dec 20 '12 at 20:04
  • See @fabian's answer for a belated but vastly superior solution. Let Java's own SourceVersion class tell you whether the String is a valid name, including whether it is a keyword. – mwoodman Mar 03 '16 at 17:41
5

I used the list of java keywords kindly offered by 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;
}
tcb
  • 2,494
  • 17
  • 20
  • 1
    This won't deal properly with names like `"com.example.true` (which is an illegal name because one _component_ of the name is a keyword). Note that the test also needs to allow names like `"com.example.true_fact"`. – Ted Hopp Dec 20 '12 at 20:02
  • 1
    Not quite fixed. It still will allow names like `"com.example.true"`. – Ted Hopp Dec 20 '12 at 20:20
  • 1
    Hope it's fine now. Nice pair programming :) – tcb Dec 20 '12 at 20:41
  • See @fabian's answer for a belated but vastly superior solution. Let Java's own SourceVersion class tell you whether the String is a valid name, including whether it is a keyword. – mwoodman Mar 03 '16 at 17:41
0

yap -

Class.forName(String className);

It returns the Class object associated with the class or interface with the given string name. And throws Exceptions

LinkageError - if the linkage fails
ExceptionInInitializerError - if the initialization provoked by this method fails
ClassNotFoundException - if the class cannot be located
Subhrajyoti Majumder
  • 38,572
  • 11
  • 72
  • 100
  • 1
    This checks whether the class exists, not whether the string is legal for use as a class name (which is what OP wants to know). – Ted Hopp Dec 20 '12 at 19:40
  • @Ted I have just give info and I think it would be enough info to make a function like MrLore suggested. – Subhrajyoti Majumder Dec 20 '12 at 19:43
  • I must disagree. OP wants to know if a name would be valid as a class name, not whether a class exists. The problem with your suggestion is that it will throw the same `ClassNotFoundException` for legal names like `"foo.bar"` (if the class does not exist) and for illegal names like `"!=?"`. – Ted Hopp Dec 20 '12 at 20:00