java 仅通过简单名称反射性地查找类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13215403/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 11:54:21  来源:igfitidea点击:

Finding a class reflectively by its simple-name alone

javaclassreflection

提问by stbamb

I was wondering if there is any given function that allows me to introspect a class without having to write the packages where the class is contained.

我想知道是否有任何给定的函数可以让我内省一个类,而不必编写包含该类的包。

For example, I want to take a look at the methods and superclasses of the class Integerin order to do that I have to specify the packages where the class is located. This will be "java.lang.Integer"

例如,我想查看Integer类的方法和超类,以便我必须指定该类所在的包。这将是“java.lang.Integer”

Instead of doing that I want to just type the class name in order to have the information of the class displayed. Just like this "Integer"

而不是这样做,我只想输入类名以便显示类的信息。就像这个“整数”

How can I make that my program just check the class name, no matter where is it located?

我怎样才能让我的程序只检查类名,不管它在哪里?

回答by rodion

Java will not stop you from creating your own my.company.Integerclass and my.other.company.Integerclass, so how it cannot know which Integerclass is the rightone.

Java 不会阻止您创建自己的my.company.Integer类和my.other.company.Integer类,因此它如何不知道哪个Integer类是正确的

The closes thing to an answer I can suggest is to create a pre-defined list of packages where you want to search the class for, and keep trying each until you find your class.

我可以建议的答案的最后一步是创建一个预定义的包列表,您要在其中搜索该类,并继续尝试每个包,直到找到您的类。

So something like:

所以像:

class ClassFinder{
  public static final String[] searchPackages = {
    "java.lang",
    "java.util",
    "my.company",
    "my.company.other" };

  public Class<?> findClassByName(String name) {
    for(int i=0; i<searchPackages.length; i++){
      try{
        return Class.forName(searchPackages[i] + "." + name);
      } catch (ClassNotFoundException e){
        //not in this package, try another
      } catch (...){
        //deal with other problems...
      }
    }
    //nothing found: return null or throw ClassNotFoundException
    return null;
  }
}

If you want to get a list of all available packages instead of hard-coding them, see here.

如果您想获得所有可用软件包的列表而不是对其进行硬编码,请参阅此处

Be warned that this method is unlikely to perform very well, so use it sparingly.

请注意,此方法不太可能执行得非常好,因此请谨慎使用。

回答by thedayofcondor

That's not possible, classes are loaded dynamically once referenced. So, there is no way to drill down the list of available packages as there is no such thing.

这是不可能的,类一旦被引用就会动态加载。因此,无法深入了解可用包的列表,因为没有这样的东西。

However, there are ways to inspect jars as these are zip files (including the standard JVM jars).

但是,有一些方法可以检查 jar,因为它们是 zip 文件(包括标准的 JVM jar)。

回答by ycomp

Borrowed code, slightly modified (...from @rodion's answer)

借用的代码,稍作修改(...来自@rodion 的回答)

/**
 * Returns first loaded Class found in the searchPackages
 * @param classname the simple class name (e.g. "String")
 * @param searchPackages String[] of packages to search.
 *                       <li>Place the more important packages at the top since the first Class
 *                           found is returned</li>
 *                       <code>//Example
 *                        public static final String[] searchPackages = {
 *                          "java.lang",
 *                          "java.util",
 *                          "my.company",
 *                          "my.company.other" };
 *                       </code>
 * @return the loaded Class or null if not found
 */
public static final Class<?> findClassByName(String classname, String[] searchPackages) {
    for(int i=0; i<searchPackages.length; i++){
        try{
            return Class.forName(searchPackages[i] + "." + classname);
        } catch (ClassNotFoundException e){
            //not in this package, try another
        }
    }
    //nothing found: return null or throw ClassNotFoundException
    return null;
}

same code modified to throw an exception if duplicate Class names found

如果发现重复的类名,则修改相同的代码以抛出异常

/**
 * Returns the loaded Class found in the searchPackages
 * @param classname the simple class name (e.g. "String")
 * @param searchPackages String[] of packages to search.
 *                       <li>Place the more important packages at the top since the first Class
 *                           found is returned</li>
 *                       <code>//Example
 *                        public static final String[] searchPackages = {
 *                        "java.lang",
 *                        "java.util",
 *                        "my.company",
 *                        "my.company.other" };
 *                       </code>
 * @throws RuntimeException if more than one class of the same classname found in multiple packages
 * @return the loaded Class (guaranteed to be unique among the searchPackages) or null if not found
 */
public static final Class<?> findClassByNameNoDupes(String classname, String[] searchPackages) {

    Class<?> foundClass = null;
    for(int i=0; i<searchPackages.length; i++){
        try{
            boolean wasNull = foundClass == null;
            foundClass = Class.forName(searchPackages[i] + "." + classname);
            if (!wasNull) throw new RuntimeException(classname + " exists in multiple packages!");
        } catch (ClassNotFoundException e){
            //not in this package, try another
        }
    }
    return foundClass;
}