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

发布于 2024-10-20 16:33:26 字数 1679 浏览 2 评论 0原文

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

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

其中 Module 是:

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

ModuleAModuleB extends Module

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

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

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 中的模块列表代码>.相反,我希望它自动填充模块包中所有模块子类型的实例。

我尝试了多种基于反射的解决方案像这样,其中涉及使用ClassLoader::getResource(String path) 检索 module 包内的每个 .class 文件,但它始终返回一个空枚举。我了解到这是由于 Dalvik 的 VM 和 Java SE 的 VM 之间的差异以及它在 classes.dex 内对 .class 文件的优化打包造成的。然后,我尝试使用 DexClassLoaderPathClassLoader/data/app/ 导入应用程序的 apk,但尝试了 getResource()<再次使用 /code> 方法。不管怎样,我认为这不是正确的方向,而且可能这个东西在 Java 中已经很 hackish/ 有缺陷了,在 Android 中更是如此。

你能建议我一种方法吗?

非常感谢。

Suppose I have my Android app's source code packaged this way:

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

where Module is:

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

, ModuleA and ModuleB extends Module:

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

and ModuleManager has some helper methods, among which one to retrieve all the Modules:

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;
    }
}

As you can see I manually filled the list of modules in ModuleManager. Instead, I would like it to be automatically filled with an instance of all the Module's subtypes in the module package.

I tried in several ways reflection-based solutions like this, which involve the use of ClassLoader::getResource(String path) to retrieve every .class file inside the module package, but it always returns an empty enumeration. I learnt this is due to the difference between Dalvik's VM and Java SE's one, and its optimized packaging of .class files inside classes.dex. I then tried to import the application's apk from /data/app/ with DexClassLoader or PathClassLoader and unsuccesfully tried their getResource() method again. Anyway I think this is not the right direction, and probably this stuff was already hackish/flawed in Java, and it would be even more in Android.

Could you suggest me a way to do that?

Thank you very much.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

心在旅行 2024-10-27 16:33:26

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

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

One way to do this in a build script, after compilation but before dex is called to create classes.dex, run a small script to get the class names in modules folder and write it to say an application.properties file to read from (or strings.xml in resources).

The disadvantage of this is it is not a pure java method you were asking for, the advantage being it will work for 2 or 10+ subclasses. Hope this helps.

骷髅 2024-10-27 16:33:26

如果您添加一个带有模块类的 XML 或属性,并从中动态创建,会怎么样...它可能会像这样

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

What if you add an XML or a Properties with the module classes and you dynamicly created from it... it might goes something like this

<modules>
    <module>
    my.app.module.ModuleA
    </module>
    <module>
    my.app.module.ModuleB
    </module>
</modules>
初吻给了烟 2024-10-27 16:33:26

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

当然,这可能适用于极少数情况,并且会牺牲类名的可读性。

Another solution could be to exploit a naming convention on classes' names and retrieve all of them one-by-one with Class.forName(className). In the example I made, if I know that all modules are named sequentially as ModuleA, ModuleB, ModuleC and so on, I can retrieve all of them starting from ModuleA and continuing until Class.forName("ModuleX") fails. If gaps were allowed but the number of modules was bounded (and very low), an exhaustive search on the entire range could be done.

Of course this could be applied in a very few cases, and at the expense of class' name readability.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文