我記得幾年前,我正在使用靜態初始化器來調用類級別的設置操作。我記得它有非常奇怪的行爲,我只是決定避開它們。也許是因爲我搞亂了最高層的命令或是一個新手。但我遇到需要重新審視它們,我想確保沒有更簡潔的更好的方法。靜態初始化的合法用法?
我知道這不是時尚,但我經常有數據驅動的類,它們維護從數據庫導入的實例的靜態列表。
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
}
當我有幾十個表驅動類像這樣的,這種模式是非常簡潔(是的,我知道它緊密結合數據/實例中的一個源類)。
但是,當我發現Google Guava的優點時,我希望使用EventBus在發佈某個事件時更新靜態列表。我會創建一個靜態最終布爾變量來調用一個初始化註冊的靜態方法。
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
private static final boolean subscribed = subscribe();
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
private static boolean subscribe() {
MyEventBus.get().register(new Object() {
@Subscribe
public void refresh(ParameterRefreshEvent e) {
stratBands = importFromDb();
}
});
return true;
}
}
這讓人討厭得很快,因爲編譯器會針對永遠不會使用的訂閱變量發出警告。此外,它只是增加了混亂。所以我想知道如果使用靜態初始化器是否可行,並且如果我不將它解耦成兩個或更多類,那麼確實沒有更好的方法。思考?
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
static {
MyEventBus.get().register(new Object() {
@Subscribe
public void refresh(ParameterRefreshEvent e) {
stratBands = importFromDb();
}
});
}
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
}
這是「不時髦」,正是因爲,正如你發現的那樣,它確實導致了「非常離奇的行爲」。通常最好不要讓這些東西是靜態的,而是將它們傳遞到明確需要的地方(或者隱式地使用依賴注入)。當他們只是創建單例或者進行純計算時,靜態初始化器是很好的,但是它們通常不應該與文件系統,數據庫或任何外部的任何事情交互。 –
我在等人說這個。我得到了我欣賞的DI範例。但是,在我們準備擴大到DI驅動的框架之前,我有點希望保持我們有更長一段時間。 – tmn
你不需要在這裏使用DI,但是如果你能夠完全實現這個功能,我會感到很驚訝,而且它會保持非常脆弱,難以測試,並且坦率地說,要花費更多的努力將採取。 –