假设我有一个基类A
(带有一个名为 的虚拟方法normalInit()
)和 300 个子类:A1, A2, A3, ...
每个子类都有一个staticInit()
静态方法,外加一个normalInit()
覆盖。(请不要问为什么;这是在生产软件中,已经给出,无法更改设计以更好地重用。实际上,这些子类是由代码生成器生成的,但现在这无关紧要。)
根据应用程序的不同执行,A1, A2, A3, ...
需要初始化一个(小)子集。换句话说,有一些数据是特定的所有实例Ai
共同共享或访问的。显然,将这些实体定义和处理为static
成员/方法是合理的(因为它们由 a 的所有实例共享Ai
)。
那么如何初始化这个子集的静态(并调用静态方法)呢?
简而言之,它不是静态初始化所有 Ai
子类的解决方案,因为只需要一个小子集(会浪费内存)。static
Java 中的行为显然提供了一个解决方案:static
当第一次访问一个类时,一个类的初始化器被初始化(我在这里忽略了一些特殊情况,例如编译器内联原始最终静态,就像在那种情况下,技术上存在没有类访问权限,仅在源代码级别上)。
问题是,我需要确定性(实际上是在预定义时间)静态初始化,因为它们的static
行为也会访问应用程序的当前静态(全局)状态。所以static
初始化器不是一个选项,我需要static
方法,在适当的地方显式地调用它们。
在所讨论的应用程序中,必须在Ai
通过迭代访问各种类的实例时完成此操作,超类ArrayList<A>
在哪里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
列表中有哪些实例。请注意,我知道静态是在编译时绑定的,而且我知道多态在这里是不可能的,所以我不是在问如何从上述循环中调用静态方法!具体调用的实例(以及它的Class
)是在运行时决定的,由于动态调度,何时normalInit()
被调用。
一个明显的解决方案是从覆盖中调用具体类的staticInit()
方法:normalInit()
public class A2 {
@Override
public void normalInit(int[] args) {
// ...
staticInit();
}
private static void staticInit() {
if (!sStaticInitialized) {
sStaticInitialized = true;
...
}
}
}
为此,Ai
必须修改生成子类的代码生成器模板。
但是这个(和上面的代码)看起来不是一个好的解决方案。我了解整体应用程序设计是否存在一些缺陷,但即使这是您的观点,如果此类声明能够通过额外的(独立的)建设性建议来增强,我将不胜感激。上述问题是否有更好的解决方案/习语?