【问题标题】:Is possible iterate over all classes inside a package with Reflection? [duplicate]是否可以使用反射遍历包内的所有类? [复制]
【发布时间】:2012-04-11 11:51:40
【问题描述】:

我有一个有一些价值的字符串。我想遍历调用特定方法的包中的所有类,如果方法返回的值等于我的字符串中的值,则创建该类的对象。

我想以动态的方式做这件事,所以如果我在这个包中添加一个类,它会自动在迭代中。

可以这样做吗? 如果没有,有办法做我想做的事吗?


我期待类似的东西。

for(Class clazz: SomeClass.listClasses("org.package")){
     //code here
}

【问题讨论】:

  • “在这个包中添加一个类”是什么意思?它是如何进入java进程的classpath的?
  • @Jeffrey 我正在阅读有关反射的信息,我认为这是唯一的方法,但我对反射一无所知。我尝试了一种“正常方式”为我在该包中的每个类添加验证,但我不想要这种方式,因为它不可扩展。
  • @MiserableVariable 在开发时,我在包中添加了一些新类(所有类都扩展了一个名为 Document 的抽象类)。
  • @RenatoDinhaniConceição 反射是解决这个问题的一种方法,但是你有没有尝试过反射?那里有相当不错的tutorials...
  • 我不明白这是一项反思的工作。更多的文件系统/类加载器工作。

标签: java reflection


【解决方案1】:

我可以想到两种方法来解决我认为您的问题,尽管它们都没有真正迭代包中的所有类。

一种是创建一个单独的文件,列出应该调用该特定方法的类。这很容易实现。您可能需要做一些创建文件的工作,但这可以自动完成。

第二个选项是在某个众所周知的地方寻找 .class 文件——比如一个文件夹或一组文件夹——然后猜测类名是什么并加载它。如果这是一个简单的开发过程,单个包中的类文件可能位于单个目录中。

【讨论】:

    【解决方案2】:

    是的,但不是一般情况下的解决方案。您必须打包代码并以特定方式调用 JVM。具体来说,您需要创建一个 Instrumentation 代理,并调用 java.lang.instrument.Instrumentation.getAllLoadedClasses()

    documentation for java.lang.instrument 包有很多关于如何创建和实例化代理的详细信息。

    【讨论】:

    • 他不仅想要加载的类,而且(大概)任何新的类文件都放在类路径的文件夹中
    • @MiserableVariable 我不知道是否清楚,但我要加载的类是在开发时定义的,而不是在运行时。
    【解决方案3】:

    不,这不可能完全可靠;但是,在许多情况下实施起来可能是切实可行的。

    由于 Java 类加载器的灵活性,特定包下定义的类在运行时可能不知道(例如,考虑一个特殊的类加载器,它可以动态定义类,可能通过从网络加载它们,或编译它们是临时的)。因此,没有标准的 Java API 允许您列出包中的类。

    然而,实际上,您可以通过在类路径中搜索所有类和 JAR 文件、构建完全限定类名的集合并根据需要搜索它们来做一些技巧。如果您确定没有活动的类加载器会像上一段中描述的那样运行,则此策略将正常工作。例如(Java 伪代码):

    Map<String, Set<String>> classesInPackage = new HashMap();
    for (String entry : eachClasspathEntry()) {
      if (isClassFile(entry)) {
        String packageName = getPackageName(entry);
        if (!classesInPackage.containsKey(packageName)) {
          classesInPackage.put(packageName, new HashSet<String>());
        }
        classesInPackage.get(packageName).add(getClassName(entry));
      } else if (isJarOrZipFile(entry)) {
        // Do the same for each JAR/ZIP file entry...
      }
    }
    classesInPackage.get("com.foo.bar"); // => Set<String> of each class...
    

    【讨论】:

    • 但是自定义类加载器可以,至少在理论上是这样。
    • @MiserableVariable:假设我编写了一个自定义类加载器,它通过返回一个类的字节码来实现defineClass(String) 方法,该类通过给定的类名定义一个空类。这是一个完全有效的类加载器,没有(实用的)方法可以列出它可以定义的每个类。
    • 是的,一般来说问题是无法解决的。但是对于特定的狭窄情况是不同的——我可能想检查文件夹名称 plugins 中的所有 .class 文件,并在每个具有 register 方法的类上创建一个实例。
    猜你喜欢
    • 2011-06-14
    • 2012-06-20
    • 1970-01-01
    • 2015-02-05
    • 2014-10-25
    • 2010-10-27
    • 2014-12-28
    • 2019-11-24
    • 1970-01-01
    相关资源
    最近更新 更多