我一直在用 Guava 的ImmutableMap
Builder
一段时间,没有过多考虑它是如何/为什么工作的。我一直在以Javadoc描述的方式使用构建器:
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();
两者似乎产生了完全相同的结果。
快速浏览一下ImmutableMap
源显示,第二个示例中的静态builder()
调用返回: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
而第二行不调用。
不,它们是相同的。第一种语法的原因是它是一个很好的单行代码。
第二种语法的原因是您可能有一个循环或其他流控制,您可能需要传递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));
}
}
在你说之前,是的,在这种情况下,FluentIterable
可能会更好 - 但这只是一个例子。
如 javadoc 中所述,生成的构建器等效于 ImmutableMap.Builder 构造函数创建的构建器。
在应用 Builder 模式时编写此类方法是一种很好的做法。这提供了一种流畅的使用方式,可以被视为"句法糖"。