我记得几年前,我正在使用静态初始化器来调用类级别的设置操作。我记得它有非常奇怪的行为,我只是决定避开它们。也许是因为我搞乱了最高层的命令或是一个新手。但我遇到需要重新审视它们,我想确保没有更简洁的更好的方法。静态初始化的合法用法?
我知道这不是时尚,但我经常有数据驱动的类,它们维护从数据库导入的实例的静态列表。
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,但是如果你能够完全实现这个功能,我会感到很惊讶,而且它会保持非常脆弱,难以测试,并且坦率地说,要花费更多的努力将采取。 –