我感兴趣的是为什么这段代码会产生语法错误,说明ImmutableMap无法解析为类型:
ImmutableMap<String, String> advice = ImmutableMap<String, String>.builder()
.put(KEY1, VAL1)
.put(KEY2, VAL2)
.build();
虽然此代码按预期工作:
ImmutableMap<String, String> advice = ImmutableMap.<String, String>builder()
.put(KEY1, VAL1)
.put(KEY2, VAL2)
.build();
这段时间不是我的心理模型应该去的地方,我希望有人可以解释为什么这个时期的“方法方面”。我正在使用Guava的ImmutableMap,但它并不完全相关我不认为。我认为这与泛型有关,但我不确定是什么,我不确定如何寻找更好的答案,因为我不知道这个概念会被称为什么。
编辑:作为参考,ImmutableMap有builder()
public static <K, V> Builder<K, V> builder() {
return new Builder<K, V>();
}
答案 0 :(得分:6)
builder()是一个静态方法,它具有与之关联的泛型类型,而不是它所定义的类。它将类似于
public static <K,V> ImmutableMap.Builder<K,V> builder() { ... }
注意:这里的<K, V>
与类的泛型类型没有任何关系。 (这不是通用的)
答案 1 :(得分:1)
由于Java实现泛型的方式,通过类型擦除(强制转换)而不是扩展,实际上只加载了一个ImmutableMap
类。其静态builder
方法因此需要解析特定的泛型重载。将变量advice
声明为ImmutableMap<String, String>
是编译器的语法糖,然后只要在advice
上调用实例方法,就会假定相关的重载。但必须单独指定ImmutableMap
上的静态方法调用。这就是泛型出现在点的方法方面的原因。
这在通过扩展实现泛型的语言中会有所不同,例如C#,其中每个通用映射类型将作为单独的类型加载到CLR中,因此ImmutableMap<String, String>
将是具有不同静态方法的不同类型到ImmutableMap<Foo, Bar>
。
答案 2 :(得分:0)
很难找到有关这个概念的信息,因为它有点模糊。我不得不搜索Angelika Langer的优秀的Generics FAQ一段时间才能找到它,即使我知道它...
无论如何,它被称为“显式类型参数规范”,并且当你想明确地指定泛型方法的类型参数时使用它,通常是因为编译器无法从上下文中推断它(例如,在链接方法调用时),或者因为你想帮助编译器在各种重载之间进行选择:
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ402
有关类型参数推断的更多信息:
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ400