是否可以使用反射遍历包内的所有类? [复制]

Posted

技术标签:

【中文标题】是否可以使用反射遍历包内的所有类? [复制]【英文标题】: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... 我不明白这是一项反思的工作。更多的文件系统/类加载器工作。 【参考方案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 方法的类上创建一个实例。

以上是关于是否可以使用反射遍历包内的所有类? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

java中如何遍历一个类的所有对象?

java中如何遍历一个类的所有对象?

java 遍历 类属性的属性值

Type反射遍历类的属性

如何遍历 Map 并克隆每个值? [复制]

遍历通用节点类,列出所有节点导致无限循环