2

I am interested why this fragment of code produces a syntax error saying ImmutableMap cannot be resolved to a type:

ImmutableMap<String, String> advice = ImmutableMap<String, String>.builder()
                    .put(KEY1, VAL1)
                    .put(KEY2, VAL2)
                    .build();

While this code works as intended:

ImmutableMap<String, String> advice = ImmutableMap.<String, String>builder()
                    .put(KEY1, VAL1)
                    .put(KEY2, VAL2)
                    .build();

The period isn't going where my mental model should and I was hoping someone could explain why the goes on the "method side" of the period. I'm using Guava's ImmutableMap, but its not entirely relevant I don't think. I think it has something to do with the generics but I'm not sure what and I'm not sure how to search to find a better answer since I don't know what the concept would be called.

EDIT: For reference, ImmutableMap has this line for builder()

public static <K, V> Builder<K, V> builder() {
    return new Builder<K, V>();
}
Nick Campion
  • 10,479
  • 3
  • 44
  • 58
  • http://stackoverflow.com/a/55679/829571 – assylias Aug 31 '12 at 14:37
  • possible duplicate of [Using the Java Guava library, how to create a ImmutableSortedSet using a Builder?](http://stackoverflow.com/questions/6362856/using-the-java-guava-library-how-to-create-a-immutablesortedset-using-a-builder) – Grzegorz Rożniecki Aug 31 '12 at 15:03

3 Answers3

6

builder() is a static method which has generic types associated with it, not the class it is defined in. It will be something like

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

Note: the <K, V> here doesn't have anything to do with the generic types of the class. (Which doesn't have to be generic)

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • So, I'm trying to piece your answer and the other by @David M together. Because this is a static method and the generic types aren't actually associated with the class when it is loaded a single time into the class loader, the method needs to have type information passed in? So, when I read the line you posted, should I read it as: ImmutableMap <-- return type | method-->builder() ? As in the method signature includes the requirements of indicating the generic types? – Nick Campion Aug 31 '12 at 14:44
  • Notionally, its the signature of the method which has the generic type. The generic types are not being passed or available at runtime in this case. – Peter Lawrey Aug 31 '12 at 14:48
1

Because of the way Java implements generics, by type erasure (casting) not expansion, there is actually only one ImmutableMap class loaded. Its static builder method is what therefore needs resolving to the specific generic overload. The declaring of the variable advice as ImmutableMap<String, String> is syntactic sugar for the compiler, which then assumes the associated overloads whenever an instance method is called on advice. But the static method call on ImmutableMap must be specified separately. That's why the generics appear on the method side of the dot.

This would be different in a language that implements generics by expansion, like C#, where each generic map type would be loaded as a separate type into the CLR, so ImmutableMap<String, String> would be a different type with different static methods to ImmutableMap<Foo, Bar>.

David M
  • 71,481
  • 13
  • 158
  • 186
0

It's hard to find information about this concept, since it is a little obscure. I had to search Angelika Langer's great Generics FAQ for a while to find it, even though I knew about it...

Anyway, it's called "explicit type argument specification", and it's used when you want to specify the type arguments for a generic method explicitly, usually because the compiler cannot infer it from the context (e.g. when chaining method calls), or because you want to help the compiler choose between various overloads:

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

More info on type argument inference:

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

Etienne Neveu
  • 12,604
  • 9
  • 36
  • 59