說我有一個基類A
(一個名爲normalInit()
虛方法),以及300個小類:A1, A2, A3, ...
每個子類有staticInit()
靜態方法,再加上一個normalInit()
覆蓋。 (請不要問爲什麼;這是在已經給出的生產軟件中,不能改變設計以便更好地重複使用,實際上,這些子類是由代碼生成器生成的,但現在這是不相關的。)從(超)子類的實例列表調用靜態方法
根據應用程序的不同執行情況,A1, A2, A3, ...
的(小)子集需要初始化。換句話說,某些特定的Ai
共享或訪問的所有實例都有一些數據。顯然,將這些實體定義爲static
成員/方法(因爲它們由Ai
的所有實例共享)是合理的。
那麼如何初始化該子集的靜態(並調用靜態方法)呢?簡而言之,這不是靜態初始化全部Ai
子類的解決方案,因爲只需要一小部分子集(將浪費內存)。 Java中的static
行爲顯然爲此提供了一個解決方案:類的初始化器在初次訪問時初始化(我在此忽略了一些特殊情況,例如,在這種情況下編譯器內聯最終靜態,從技術上來說,沒有課程訪問權限,只是在源代碼級別)。
的問題是,我需要確定性(實際上是在預定義的時間)靜態初始化,因爲他們的行爲static
也可以訪問應用程序的當前靜態(全局)狀態。因此,static
初始值設定項不是一個選項,我需要static
方法,以在適當的位置顯式調用它們。
在有問題的應用程序中,必須在遍歷ArrayList<A>
(其中A
是超類)中訪問各種Ai
類的實例時完成此操作。
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
在列表中有實例。 注意,我知道靜態在編譯時綁定,我知道多態是不可能在這裏,所以我不問如何調用上述循環的靜態方法!當調用normalInit()
時,由於動態調度,具體稱爲實例(以及因此它的Class
)在運行時決定。
表觀溶液是調用具體類從normalInit()
倍率staticInit()
方法:
public class A2 {
@Override
public void normalInit(int[] args) {
// ...
staticInit();
}
private static void staticInit() {
if (!sStaticInitialized) {
sStaticInitialized = true;
...
}
}
}
對於這一點,該生成Ai
小類中所述的代碼生成的模板必須進行修改。
但是,這(和上面的代碼)看起來不是一個很好的解決方案。我瞭解整體應用程序設計是否存在一些缺陷,但即使這是您的觀點,如果此類索賠增加了額外(獨立)建設性意見,我將不勝感激。上述問題是否有更好的解決方案/成語?
您是否嘗試過反射?調用由類名定義的不同類的一個靜態方法作爲字符串... –
這將是一個類似的解決方案(只是比現在慢),不是嗎?我仍然需要存儲哪些Ai類名已經通過反射訪問(調用它們的靜態方法)。 –
使用反射,您可以直接訪問靜態方法,而不用包裝它。缺點是在迭代之前必須將類的名稱設置爲String []。 –