当前位置: 首页 > 知识库问答 >
问题:

从子类实例的(超类)列表调用静态方法

湛同
2023-03-14

假设我有一个基类a(具有一个名为normalinit())的虚拟方法)和300个子类:A1,A2,A3,...每个子类都有一个staticinit()静态方法,外加一个normalinit()重写。(请不要问为什么;这是在一个生产软件中,已经给出了,不能为了更好的重用而更改设计。实际上,那些子类是由一个代码生成器生成的,但现在这已经不相关了。)

根据应用程序的不同执行,需要初始化A1,A2,A3,...的(小)子集。换句话说,有一些数据是特定AI的所有实例共同共享或访问的。显然,将这些实体定义为静态成员/方法(因为它们由AI的所有实例共享)是合理的。

那么如何初始化这个子集的静态(并调用静态方法)呢?

简单地说,静态初始化所有ai子类并不是一个解决方案,因为只需要一个很小的子集(会浪费内存)。Java中的statice行为显然给出了一个解决方案:类的statice初始化器在第一次访问类时被初始化(这里我忽略了一些特殊情况,例如编译器内联pritimive final statics,在这种情况下,技术上没有类访问,只是在源代码级别)。

问题是,我需要确定性的(实际上是在预定义时间)静态初始化,因为它们的statice行为也访问应用程序的当前静态(全局)状态。因此static初始化器不是一个选项,我需要static方法,以便在适当的位置显式调用它们。

在所讨论的应用程序中,当通过迭代ArrayList访问各种AI类的实例时,必须这样做,其中A是超类。

for (int i = 0; i < list.size(); ++i) {
        list[i].normalInit(args); // normalInit() is an instance method
    }

该列表由AI实例组成(例如,950个A1实例、1750个A2实例等,按未排序的“随机”顺序)。

换句话说,我没有访问具体类名的权限(所以我不能只调用a4.staticinit()),因为我不知道哪个ai在列表中有实例。注意,我知道静态是在编译时绑定的,而且我知道这里不可能有多态性,所以我不是在问如何从上面的循环调用静态方法!在调用normalinit()时,由于动态调度,具体调用的实例(以及它的)是在运行时决定的。

一个明显的解决方案是从normalinit()重写调用具体类的“staticinit()”方法:

public class A2 {   

    @Override
    public void normalInit(int[] args) {
        // ...       

        staticInit();
    }

    private static void staticInit() {
           if (!sStaticInitialized)  {
                sStaticInitialized = true;
                ...
           }
    }
}

为此,必须修改生成ai子类的代码生成器模板。

但这(和上面的代码)看起来不像是一个好的解决方案。我理解如果整个应用程序的设计有一些缺陷,但即使这是你的观点,我会感谢这样的主张,以补充额外的(独立的)建设性意见。对于上述问题,有没有更好的解决方案/习语?


共有1个答案

卜盛
2023-03-14

好的,使用反射来回答它:

String classPrefixName = "com.your.company.A";
for (int i = 0; i< 300; i++) {
    Class<?> clazz = Class.forName(classPrefixName+i); //look for the class
    Method method = clazz.getDeclaredMethod("staticInit"); //look for the method
    method.invoke(null); //invoke(null), since it's a static method
}

这样,您就不需要将静态方法包装在实例方法中。

 类似资料:
  • 我正在学习java入门课程,我们刚刚开始学习继承。我正在做一项任务,要求我们创建一个具有名称和年龄的“Pet”超类;和三个子类,每个都有自己独特的特征(我选择了“狗”、“猫”和“鸟”)。在我们构建了所有这些之后,我们将创建一个主类来测试一切,这就是我遇到问题的地方。我试图为这些独特的特性调用

  • 问题内容: 我正在学习Java入门课程,我们才刚刚开始学习继承。我正在完成一项任务,要求我们创建一个具有名称和年龄的“宠物”超类。和三个子类,每个子类都有自己的独特特征(我选择了“狗”,“猫”和“鸟”)。构建完所有这些之后,我们将创建一个Main类来测试所有内容,这就是我遇到问题的地方。我试图在中调用这些独特特征的方法,但似乎只能找到超类中的方法。 这是主类: 这是我的超人 这是子类之一(它们看起

  • 问题内容: 如果我用Java创建类的实例,为什么最好静态地调用同一类的静态方法,而不是使用this.method()? 当我尝试通过this.staticMethod()从自定义类的构造函数中调用静态方法staticMethod()时,我收到Eclipse的警告。 与 谁能解释为什么这是一件坏事?在我看来,编译器应该已经分配了对象的实例,因此静态分配内存将是不必要的开销。 编辑: 我听到的要点是,

  • 我需要从AsyncTask调用一个非静态方法 必须在onPostExecute中调用此方法 我用过: 编辑:我尝试过: 投掷:

  • 我在调用覆盖方法的子类方法时遇到了问题,所以我创建了一个小应用程序来测试它。当超类调用其子类覆盖的方法时,仍然调用超类的方法版本,而不是子类的版本,后者覆盖了超类的方法,应该是被调用的方法。 预期输出:

  • 为什么我们不能在子类B中声明一个实例方法,它与父类a中的静态方法共享相同的签名? 在上面的代码中,由于A没有该名称的实例方法,并且由于Java允许对象访问静态方法,所以指向B的类型为A的对象A可以调用它中存在的静态方法(类A)。但是编译器抛出一个错误“实例方法不能重写静态方法”为什么? 注意:我可以理解,如果一个类不允许两个方法使用相同的方法名,即使其中一个是实例,另一个是静态的。但是我不明白为什