番石榴不可变地图生成器语法

2022-09-02 04:24:49

我已经使用番石榴一段时间了,没有考虑它是如何工作的/为什么。我一直在以Javadoc描述的方式使用构建器:ImmutableMapBuilder

ImmutableMap<String, Integer> WORD_TO_INT =
          new ImmutableMap.Builder<String, Integer>()
              .put("one", 1)
              .put("two", 2)
              .put("three", 3)
              .build();

我还在其他地方看到了这种语法的SO示例:

ImmutableMap<String,Integer> myMap = ImmutableMap.<String, Integer>builder()
    .put("one", 1) 
    .put("two", 2) 
    .put("three", 3) 
    .build();

两者似乎都产生了完全相同的结果。

快速浏览一下源代码,就会发现第二个示例中的静态调用返回:ImmutableMapbuilder()new Builder<K, V>()

这两种方法之间似乎没有任何功能差异。

引擎盖下有什么区别吗?有什么理由偏爱其中之一?

编辑:添加字节码差异。

生成的字节码几乎完全相同,只有一行:

方法 1():Builder<K,V>

static {};
     0  new com.google.common.collect.ImmutableMap$Builder [12]
     3  dup
     4  invokespecial com.google.common.collect.ImmutableMap$Builder() [14]
     7  ldc <String "key1"> [17]
     ........

方法 2:(<K,V>builder())

static {};
     0  invokestatic com.google.common.collect.ImmutableMap.builder() : com.google.common.collect.ImmutableMap$Builder [12]
     3  ldc <String "key1"> [18]
     ........

在那之后,它们几乎是相同的,考虑到源的差异,第一行不同是有道理的,但我不确定为什么第一行调用而第二行不调用。dup


答案 1

不,它们是相同的。第一种语法的原因是它是一个不错的单行代码。

第二种语法的原因是您可能有一个循环或其他流控制,您可能需要传递。Builder

例如:

public static void main(final String[] args) throws Exception {
    final ImmutableList.Builder<Integer> lb = ImmutableList.builder();
    for (final String arg : args) {
        lb.add(Integer.parseInt(arg));
    }
}

在你说出来之前,是的,在这种情况下,a可能会更好 - 但这只是一个例子。FluentIterable


答案 2

javadoc 中所述,生成的构建器等效于 ImmutableMap.Builder 构造函数创建的构建器。

在应用 Builder 模式时编写这样的方法是一种很好的做法。这提供了一种流畅的使用方式,可以被认为是一种“句法糖”。