【发布时间】:2015-04-06 17:37:35
【问题描述】:
我记得几年前我使用静态初始化程序来调用类级别的设置操作。我记得它有非常奇怪的行为,我只是决定避开它们。也许是因为我搞乱了上下顺序或者是新手。但我遇到了重新审视它们的需要,我想确保没有更好的方法可以简洁。
我知道这并不流行,但我经常有数据驱动的类来维护从数据库导入的实例的静态列表。
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 驱动的框架之前,我有点希望能够将我们所拥有的框架保持更长时间。
-
你不需要在这里使用 DI,但如果你能让它工作,我会感到惊讶,它仍然非常脆弱,难以测试,坦率地说它会付出更多的努力,而不是正确地去做。
-
在那一点上我可能会避免使用静态初始化器。
标签: java guava static-initialization event-bus