获取包中基类的所有子类的实例

时间:2011-03-03 16:04:44

标签: android reflection package classloader

假设我的Android应用程序的源代码以这种方式打包:

src/
   my/
      app/
         Module.java
         ModuleManager.java
         module/
            ModuleA.java
            ModuleB.java

其中Module是:

public abstract class Module {
    public abstract void run();
}

ModuleAModuleB延伸Module

public class ModuleA extends Module {
    @Override
    public void run() { /* do something */  }
}

ModuleManager有一些辅助方法,其中一个用于检索所有Module s:

public class ModuleManager {

    private final static List<Module> modules;
    static {
        List<Module> tmp= new ArrayList<Module>();
        tmp.add(new ModuleA());
        tmp.add(new ModuleB());
        modules= Collections.unmodifiableList(tmp);
    }

    public static List<Module> getModules(){
        return modules;
    }
}

如您所见,我手动填写了ModuleManager中的模块列表。相反,我希望自动填充 module 包中所有Module子类型的实例。

我尝试了几种基于反射的解决方案like this,其中涉及使用ClassLoader::getResource(String path)检索模块包中的每个.class文件,但它总是返回空的枚举。我了解到这是由于Dalvik的VM和Java SE之间的区别,以及它在 classes.dex 中的.class文件的优化打包。然后,我尝试使用DexClassLoaderPathClassLoader / data / app / 导入应用程序的apk,并再次尝试不再尝试getResource()方法。无论如何,我认为这不是正确的方向,可能这些东西在Java中已经是hackish /有缺陷,而且在Android中会更多。

你能建议我这样做吗?

非常感谢。

3 个答案:

答案 0 :(得分:2)

在构建脚本中执行此操作的一种方法是,在编译之后但在调用dex来创建classes.dex之前,运行一个小脚本来获取modules文件夹中的类名并将其写入以说明要读取的application.properties文件from(或资源中的strings.xml)。

这样做的缺点是它不是你要求的纯java方法,它的优点是适用于2或10+个子类。希望这会有所帮助。

答案 1 :(得分:1)

如果您使用模块类添加XML或属性并从中动态创建它会怎样......它可能会是这样的

<modules>
    <module>
    my.app.module.ModuleA
    </module>
    <module>
    my.app.module.ModuleB
    </module>
</modules>

答案 2 :(得分:1)

另一个解决方案可能是利用类名称的命名约定,并使用Class.forName(className)逐个检索所有这些约定。在我做的示例中,如果我知道所有模块按顺序命名为ModuleAModuleBModuleC等等,我可以从ModuleA开始检索所有模块并继续直到Class.forName("ModuleX")失败。如果允许间隙但模块的数量有限(并且非常低),则可以对整个范围进行详尽的搜索。

当然,这可以在很少的情况下应用,并且以代表名称的可读性为代价。