【问题标题】:How to check if the class name is valid?如何检查类名是否有效?
【发布时间】:2012-12-08 09:16:25
【问题描述】:

Java中是否有检查字符串是否可以用作类名的方法?

【问题讨论】:

  • 他问的是这个名字是否是一个合法的名字,而不是这个类是否真的存在。 (我认为)
  • 是的,我想创建一个带有反射和名称的新类...所以我必须检查名称是否有效
  • 那么听起来您确实想知道字符串是否引用了有效的类。请参阅下面的答案。我以为您在检查名称是否遵循允许命名类的规则。
  • 这不是 stackoverflow.com/questions/5205339/… 的重复,因为发帖者并不关心解决方案是否是正则表达式

标签: java class methods


【解决方案1】:

呸——

Class.forName(String className);

它返回与具有给定字符串名称的类或接口关联的 Class 对象。 并抛出Exceptions

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

【讨论】:

  • 这会检查类是否存在,而不是字符串是否可以用作类名(这是 OP 想知道的)。
  • @Ted 我刚刚提供了信息,我认为这些信息足以制作像 MrLore 建议的功能。
  • 我一定不同意。 OP 想知道一个名称是否作为类名有效,而不是一个类是否存在。您的建议的问题在于,对于 "foo.bar" 等合法名称(如果该类不存在)和 "!=?" 等非法名称,它将抛出相同的 ClassNotFoundException
【解决方案2】:

很简单,使用Class.forName(String name) 方法,可用于测试如下:

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

编辑:如果,正如 dashrb 所说,您正在寻求一种方法来确定是否可以将 String 用作类名(而不是如果已经有一个使用该名称的类),那么您需要的是结合我上面发布的方法(翻转布尔值,因为您不能重用类名),并结合检查字符串是否为 Java 保留关键字。我最近遇到了类似的问题,并为它制作了一个实用程序类,你可以找到here。我不会为你写,但你基本上只需要添加一个!JavaKeywords.isKeyword(className)的支票。

编辑 2:当然,如果您还想强制执行普遍接受的编码标准,您可以确保类名以大写字母开头:

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

编辑 3:正如 Ted Hopp 指出的那样,即使包含 java 关键字也会使类名无效,并且由于 JavaKeywords 在我的一个生产应用程序中使用,我已经创建了一个 updated version,其中包括方法containsKeyword(String toCheck) 也将检查这种可能性。方法如下(请注意,您也需要类中的关键字列表):

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()

【讨论】:

  • 首字母不必大写。
  • @tcb 我知道,但是让类以大写字母开头是相当标准的做法,我相当确定内置包中的每个非原始类都是如此。
  • 这只处理简单的名字。但是像com.example.Foo 这样的限定名是合法的类名。
  • 查看@fabian 的回答,了解迟到但非常优越的解决方案。让Java自带的SourceVersion类告诉你String是否为合法名称,包括是否为关键字。
【解决方案3】:

我使用了 MrLore 提供的 java 关键字列表。

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;
}

【讨论】:

  • 这将无法正确处理像"com.example.true 这样的名称(这是一个非法名称,因为名称的一个组件 是关键字)。请注意,测试还需要允许"com.example.true_fact" 之类的名称。
  • 不太固定。它仍然允许使用 "com.example.true" 之类的名称。
  • 希望现在没事。不错的结对编程:)
  • 查看@fabian 的回答,了解迟到但非常优越的解决方案。让Java自带的SourceVersion类告诉你String是否为合法名称,包括是否为关键字。
【解决方案4】:

SourceVersion.isName 可用于检查完全限定名称。

如果不应该允许.s,可以这样检查:

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

【讨论】:

  • 你迟到了三年,但这正是要走的路。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-21
  • 2010-12-20
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多