2

我很感兴趣为什么这段代码会产生语法错误,说 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>();
}
4

3 回答 3

6

builder() 是一个静态方法,它具有与之关联的泛型类型,而不是它定义的类。它将类似于

public static <K,V> ImmutableMap.Builder<K,V> builder() { ... }

注意:<K, V>这里与类的泛型类型没有任何关系。(不一定是通用的)

于 2012-08-31T14:28:47.323 回答
1

由于 Java 实现泛型的方式,通过类型擦除(转换)而不是扩展,实际上只ImmutableMap加载了一个类。因此,它的静态builder方法需要解决特定的泛型重载。将变量声明adviceImmutableMap<String, String>编译器的语法糖,然后在调用实例方法时假定相关的重载advice。但是静态方法调用ImmutableMap必须单独指定。这就是为什么泛型出现在点的方法一侧的原因。

这在通过扩展实现泛型的语言(例如 C#)中会有所不同,其中每个泛型映射类型将作为单独的类型加载到 CLR 中,因此ImmutableMap<String, String>具有不同静态方法的不同类型将用于ImmutableMap<Foo, Bar>.

于 2012-08-31T14:28:15.670 回答
0

很难找到有关此概念的信息,因为它有点晦涩难懂。我不得不搜索 Angelika Langer 的伟大泛型常见问题解答一段时间才能找到它,即使我知道它......

无论如何,它被称为“显式类型参数规范”,当您想要显式指定泛型方法的类型参数时使用它,通常是因为编译器无法从上下文推断它(例如,在链接方法调用时),或者因为您想要帮助编译器在各种重载之间进行选择:

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ402

有关类型参数推断的更多信息:

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ400

于 2012-09-02T09:48:37.647 回答