tmn*_*tmn 6 java static-initialization guava event-bus
我记得几年前我使用静态初始化程序来调用类级别的设置操作.我记得它有非常奇怪的行为,我只是决定避开他们.也许是因为我弄乱了最上层的订单或成为新手.但我遇到了重新审视它们的需要,我想确保没有一种更简洁的方法.
我知道它不时髦,但我经常有数据驱动的类,它们维护从数据库导入的静态实例列表.
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
}
Run Code Online (Sandbox Code Playgroud)
当我有几十个像这样的表驱动类时,这个模式非常简洁(是的,我知道它将类与一个数据/实例源紧密结合).
但是,当我发现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;
}
}
Run Code Online (Sandbox Code Playgroud)
这很烦人,因为编译器会对从未使用过的订阅变量发出警告.而且,它只是增加了混乱.所以我想知道使用静态初始化器是否犹豫不决,如果我不将它分成两个或更多类,那么确实没有更好的方法.思考?
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
}
Run Code Online (Sandbox Code Playgroud)
所以我想知道使用静态初始化器是否合理
有趣的是
private static final boolean subscribed = subscribe();
Run Code Online (Sandbox Code Playgroud)
和
private static final boolean subscribed;
static {
subscribed = subscribe();
}
Run Code Online (Sandbox Code Playgroud)
被编译为完全相同的字节码。因此,使用不必要的静态变量绝对更糟糕。
但在我们准备好扩展到 DI 驱动的框架之前,
发现吉斯。不要称其为框架(尽管它是)。它易于使用,让您摆脱static.
或者手动进行。通过删除所有静态修饰符来重写您的类,并将其传递到您需要的任何地方。有时它相当冗长,但明确声明依赖关系允许您单独测试类。
事实就是这样,StratBand无论被测试的方法多么微不足道,您都无法在不访问数据库的情况下进行测试。StratBand问题在于每个实例与所有 s 列表的耦合StratBand。
此外,您无法测试依赖于stratBands内容的行为,因为它总是从数据库加载(当然,您可以相应地填充数据库,但这很痛苦)。
对于初学者,我将创建StratBandManager(或StratBands任何您喜欢的名称)并将所有静态功能移至其中。为了轻松过渡,我会创建一个带有静态助手的临时类,例如
private static StratBandManager stratBandManager = new StratBandManager();
public static ImmutableList<StratBand> stratBands() {
return stratBandManager.stratBands();
}
Run Code Online (Sandbox Code Playgroud)
然后全部弃用并用 DI 替换(使用 Guice 或手动执行)。
我发现Guice 即使对于小项目也很有用。开销很小,因为通常没有或几乎没有任何配置。