假设我有一个基类A (带有一个名为normalInit()的虚拟方法)和300个子类:A1, A2, A3, ...每个子类都有一个staticInit()静态方法,外加一个normalInit()覆盖。(请不要问为什么,这是在一个生产软件,已经给,不能改变设计,以便更好的重用。实际上,这些子类是由代码生成器生成的,但这现在已经无关紧要了。)
根据应用程序的不同执行情况,需要初始化A1, A2, A3, ...的(小)子集。换句话说,有些数据通常是特定Ai的所有实例共享或访问的。显然,将这些实体定义为static成员/方法是合理的(因为它们被Ai的所有实例所共享)。
那么如何初始化这个子集的静力学(并调用静态方法)呢?
简而言之,它不是静态初始化all Ai子类的解决方案,因为只需要一个小子集(这将浪费内存)。Java中的static行为显然给出了一个解决方案:类的static初始化器是在第一次访问类时初始化的(这里我忽略了一些特殊情况,例如编译器内联了原始静力学,在技术上没有类访问,只是在源代码级别)。
问题是,我需要确定性(实际上是在预定义的时间)静态初始化,因为它们的static行为还访问应用程序的当前静态(全局)状态。因此,static初始化器不是一个选项,我需要static方法,在适当的位置显式调用它们。
在所讨论的应用程序中,当通过迭代访问各种Ai类的实例时,必须这样做,其中A是超类。
for (int i = 0; i < list.size(); ++i) {
list[i].normalInit(args); // normalInit() is an instance method
}该列表由Ai实例(例如,A1的950个实例、A2的1750个实例等)组成,这些实例按“随机”顺序排列。
换句话说,我无法访问具体的类名(所以我不能只调用A4.staticInit()),因为我不知道列表中有哪个Ai实例。备注,我知道静态在编译时是绑定的,而且我知道在这里不可能存在多态性,所以我不是在问如何从上面的循环调用静态方法!具体调用的实例(以及它的Class)是在运行时通过动态调度在调用normalInit()时决定的。
一个明显的解决方案是从staticInit()覆盖调用具体类的normalInit()方法:
public class A2 {
@Override
public void normalInit(int[] args) {
// ...
staticInit();
}
private static void staticInit() {
if (!sStaticInitialized) {
sStaticInitialized = true;
...
}
}
}为此,必须修改生成Ai子类的代码生成器模板。
但是这个(和上面的代码)看起来并不是一个很好的解决方案。我理解整个应用程序设计是否有一些缺陷,但即使这是你的观点,我也希望这些声明能得到更多的(独立的)建设性的建议。对上述问题是否有更好的解决办法/成语?
发布于 2013-01-04 18:34:32
好的,使用反射回答它:
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
}这样,您就不需要将静态方法包装在实例方法中。
https://stackoverflow.com/questions/14162558
复制相似问题