【发布时间】:2013-12-02 19:12:41
【问题描述】:
我就是这样做的(安卓代码)
private volatile static WifiManager wm;
private static WifiManager wm(Context ctx) {
WifiManager result = wm;
if (result == null) {
synchronized (WifiMonitor.class) { // the enclosing class
result = wm;
if (result == null) {
result = wm = (WifiManager) ctx
.getSystemService(Context.WIFI_SERVICE);
if (result == null) throw new WmNotAvailableException();
}
}
}
return result;
}
Bloch in Effective Java 推荐:
// Lazy initialization holder class idiom for static fields
private static class FieldHolder {
static final FieldType field = computeFieldValue();
}
static FieldType getField() {
return FieldHolder.field;
}
这具有省去同步的优点,并且 JVM 优化了字段访问。问题是我需要一个 Context 对象。所以:
- 有没有办法让 Bloch 的模式适应我的情况(
computeFieldValue()需要一个参数)? - 如果没有,有没有办法execute around ?代码很微妙,我宁愿把它放在一个地方,只传递所需的行为
- 最后但并非最不重要 - 有没有办法仅通过
wm()方法强制访问缓存字段 (wm) ?所以我可以避免 NPE 等。其他语言为此使用属性
【问题讨论】:
-
该方案依赖于在调用 getField 之前未初始化的 FieldHolder 类。但是,JVM 规范对于何时可以进行类初始化有很大的余地,因此可以更早地进行。
-
坦率地说,使用
synchronized的技术是“显而易见的”,易于理解,并且不依赖于任何晦涩或未记录的行为。我看不出有什么问题。如果您愿意,您可以随时将“内部”放在同步的静态方法中,以将其划分得更多。 -
@HotLicks:这是问题 2 :)
标签: java static initialization lazy-loading field