静态初始化程序的合法用途?
Legitimate uses for static initializer?
我记得几年前我使用静态初始化程序来调用 class 级别的设置操作。我记得它有非常奇怪的行为,我只是决定避开它们。也许是因为我弄乱了上下顺序或者是新手。但我遇到了重新审视它们的需要,我想确保没有更好的方法同样简洁。
我知道这不流行,但我经常使用数据驱动的 classes 维护从数据库导入的静态实例列表。
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
}
当我有几十个 table 驱动的 classes 时,这种模式非常简洁(是的,我知道它将 class 与一个 data/instances).
然而,当我发现 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;
}
}
这很快就变得烦人了,因为编译器会对从未使用过的订阅变量发出警告。此外,它只是增加了混乱。所以我想知道使用静态初始化器是否合乎规范,如果我不将其分离为两个或更多 classes,真的没有更好的方法。想法?
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
}
So I'm wondering if it is kosher to use the static initializer
有趣的是
private static final boolean subscribed = subscribe();
和
private static final boolean subscribed;
static {
subscribed = subscribe();
}
被编译成完全相同的字节码。所以使用不必要的静态变量更糟。
But until we are ready to scale up to a DI-driven framework,
发现Guice。不要称它为框架(尽管它是)。它易于使用,让您摆脱 static
.
或者手动完成。通过删除所有静态修饰符重写 class 并将其传递到任何需要的地方。有时它相当冗长,但明确说明依赖关系允许您单独测试 classes。
事情是这样的,你无法在不访问数据库的情况下测试 StratBand
,无论被测试的方法多么微不足道。问题是每个 StratBand
实例与所有 StratBand
的列表的耦合。
此外,您无法测试依赖于 stratBands
内容的行为,因为它总是从数据库中加载(当然,您可以相应地填充您的数据库,但这很麻烦)。
首先,我将创建 StratBandManager
(或 StratBands
或您喜欢的任何名称)并将所有静态功能移至其中。为了简化过渡,我会创建一个 temporary class 和静态助手,例如
private static StratBandManager stratBandManager = new StratBandManager();
public static ImmutableList<StratBand> stratBands() {
return stratBandManager.stratBands();
}
然后全部弃用并用 DI 替换它(使用 Guice 或手动执行)。
I find Guice 即使对于小型项目也很有用。开销很小,因为通常没有或几乎没有任何配置。
我记得几年前我使用静态初始化程序来调用 class 级别的设置操作。我记得它有非常奇怪的行为,我只是决定避开它们。也许是因为我弄乱了上下顺序或者是新手。但我遇到了重新审视它们的需要,我想确保没有更好的方法同样简洁。
我知道这不流行,但我经常使用数据驱动的 classes 维护从数据库导入的静态实例列表。
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
}
当我有几十个 table 驱动的 classes 时,这种模式非常简洁(是的,我知道它将 class 与一个 data/instances).
然而,当我发现 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;
}
}
这很快就变得烦人了,因为编译器会对从未使用过的订阅变量发出警告。此外,它只是增加了混乱。所以我想知道使用静态初始化器是否合乎规范,如果我不将其分离为两个或更多 classes,真的没有更好的方法。想法?
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
}
So I'm wondering if it is kosher to use the static initializer
有趣的是
private static final boolean subscribed = subscribe();
和
private static final boolean subscribed;
static {
subscribed = subscribe();
}
被编译成完全相同的字节码。所以使用不必要的静态变量更糟。
But until we are ready to scale up to a DI-driven framework,
发现Guice。不要称它为框架(尽管它是)。它易于使用,让您摆脱 static
.
或者手动完成。通过删除所有静态修饰符重写 class 并将其传递到任何需要的地方。有时它相当冗长,但明确说明依赖关系允许您单独测试 classes。
事情是这样的,你无法在不访问数据库的情况下测试 StratBand
,无论被测试的方法多么微不足道。问题是每个 StratBand
实例与所有 StratBand
的列表的耦合。
此外,您无法测试依赖于 stratBands
内容的行为,因为它总是从数据库中加载(当然,您可以相应地填充您的数据库,但这很麻烦)。
首先,我将创建 StratBandManager
(或 StratBands
或您喜欢的任何名称)并将所有静态功能移至其中。为了简化过渡,我会创建一个 temporary class 和静态助手,例如
private static StratBandManager stratBandManager = new StratBandManager();
public static ImmutableList<StratBand> stratBands() {
return stratBandManager.stratBands();
}
然后全部弃用并用 DI 替换它(使用 Guice 或手动执行)。
I find Guice 即使对于小型项目也很有用。开销很小,因为通常没有或几乎没有任何配置。