2011-03-03 65 views
1

假设我有我的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的所有子类型的实例模块包。

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

你能告诉我一种方法吗?

非常感谢。

回答

2

一个在构建脚本来做到这一点的方式,后编译之前,但在dex被调用来创建classes.dex之前,运行一个小脚本以获取modules文件夹中的类名称,并将其写入以声明要从中读取的application.properties文件(或resources.xml中的strings.xml)。

这样做的缺点是它不是您要求的纯java方法,其优点是它可以用于2个或10个以上的子类。希望这可以帮助。

+0

谢谢,这是一个好主意! – 2011-03-04 09:52:47

1

如果你添加一个XML或属性与模块类和你动态地从它创造......它可能是这样的

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

谢谢你提到Java的'Property',我从来没有搞砸过它,但它似乎是一个有趣的机制。 – 2011-03-04 09:56:00

1

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

当然,这可以应用在极少数情况下,并以类的名称可读性为代价。