是否可以使用Reflection迭代包内的所有类?

时间:2012-03-27 21:44:02

标签: java reflection

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

我想以动态方式执行此操作,因此如果我在此包中添加一个类,它将自动处于迭代中。

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


我期待像。

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

3 个答案:

答案 0 :(得分:8)

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

由于Java类加载器的灵活性,在特定包下定义的类在运行时可能不知道(例如,考虑一个特殊的类加载器,它可以即时定义类,可能是通过从网络加载它们,或者编译他们ad-hoc)。因此,没有标准的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...

答案 1 :(得分:2)

我可以想出两种解决我认为你的问题的方法,虽然它们都没有真正迭代一个包中的所有类。

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

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

答案 2 :(得分:1)

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

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