这是 Java Lazy-Getter 的实际快捷方式吗

Luk*_*kas 1 java getter lazy-loading lazy-evaluation lazy-initialization

以下内容与其说是一个问题,不如说是一个评估请求。

因此,您很可能熟悉以下惰性 getter 模式。

private Object obj;

public Object getObject() {
 if(obj==null) {
  obj = new Object();
 }
 return obj;
}
Run Code Online (Sandbox Code Playgroud)

那个代码

  • 需要一个类变量
  • 在 getter 中需要一些逻辑

所以最近一个同事和我想出了以下界面(简化):

public interface LazyGetterSupport {

default Object get(Supplier<Object> impl) {
    String key = impl.getClass().getName();
    Object retVal;
    if ((retVal = getInstanceCache().get(key)) == null) {
        retVal = impl.get();
        getInstanceCache().put(key, retVal);
    }
    return retVal;
}

Map<String, Object> getInstanceCache();
}
Run Code Online (Sandbox Code Playgroud)

旁注:不使用 HashMap#computeIfAbsent bc of Bug-8071667

然后该接口由您要使用惰性获取器的类实现。您需要提供getInstanceCache()如下实现:

private Map<String, Object> instanceCache;

@Override
public Map<String, Object> getInstanceCache() {
    if (instanceCache == null) {
        instanceCache = new HashMap<>();
    }
    return instanceCache;
}
Run Code Online (Sandbox Code Playgroud)

但鉴于您可以开始重写该类(和子类)中的所有其他惰性 getter,如下所示:

public Object getObject() {
    return get(Objetct::new);
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为我们impl.getClass().getName();在接口中使用的键实际上对于我们在其 get 方法的实现中使用的每个 lambda 始终是唯一的。然而,至少在我们的 VM 的生命周期内,每个调用站点都将保持不变。

好处是显而易见的。我们不再需要为每个惰性吸气剂创建一个类变量,吸气剂本身变得更短。这可能没有什么不同,但在我们的用例中,我们经常有包含 20 多个 UI 元素的 Lazy Getter 的类。这就是这项新技术大放异彩的地方。

我很想知道您对这种方法的看法,以及您是否对在生产中使用它有任何顾虑。

lex*_*ore 5

或者您可以简单地@Getter(lazy=true)Project Lombok使用。