泛型方法的类型参数有什么作用?

时间:2012-08-31 14:25:45

标签: java guava

我感兴趣的是为什么这段代码会产生语法错误,说明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,但它并不完全相关我不认为。我认为这与泛型有关,但我不确定是什么,我不确定如何寻找更好的答案,因为我不知道这个概念会被称为什么。

编辑:作为参考,ImmutableMapbuilder()

这一行
public static <K, V> Builder<K, V> builder() {
    return new Builder<K, V>();
}

3 个答案:

答案 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