9

I am new to Groovy, and I have a question regarding to the use of map:

I know I can do:

def map = [key:"value"]

But what does it mean if I do this:

Map<String, String> map = ["1":1, "2":"2"]

This code compiles, but the map is not really a String->String map:

map.each({println it.key + ":" + it.value + "[" + it.value.class + "]"})

It prints:

1:1[class java.lang.Integer]

2:2[class java.lang.String]

Can anyone helps me to understand how come a map explicitly typed with String->String can be assigned to a map object that contains String->Integer? Thank you!

=== Update ===

Thanks for the link provided by @GrailsGuy, if I am using @TypeChecked for the above code wrapped in a method, it will throw an error:

[Static type checking] - Incompatible generic argument types. Cannot assign java.util.Map <java.lang.String, java.io.Serializable> to: java.util.Map <String, String>

The explanation makes perfect sense now.

Community
  • 1
  • 1
Eric
  • 93
  • 1
  • 5

2 Answers2

8

This forum post talks about Groovy ignoring generics, specifically:

Groovy is a dynamically typed language, but you can statically declare the types of variables. Generics on the JVM are erased at compile time and only the raw type is available to the VM (this is true both for groovy and Java). In Java, there is compile time checking to ensure that you don't stuff an int into a list of strings. But, Groovy does not check types at compile time.

So, this means that the type parameter is not checked at compile time and not available at runtime.

Igor
  • 30,885
  • 14
  • 70
  • 107
  • hmm... then what's the point to allow generic syntax in groovy? – ZhongYu Apr 02 '13 at 03:08
  • 1
    @zhong.j.yu To keep the compiler syntax checker heppy. Very little type enforcement is done especially at compile time. Groovy is very loose in terms of type enforcement and makes extensive use of `Object` types – Reimeus Apr 02 '13 at 03:12
  • wouldn't the compiler be happier if it doesn't support generics at all? – ZhongYu Apr 02 '13 at 03:14
  • 2
    Thank you @GrailsGuy, the post mentioned TypeChecked annotation, which is very interesting. – Eric Apr 02 '13 at 03:23
3

Eric,

I suspect this is caused by type erasure explained here and here. Since groovy is compiled into byte code, at the byte code level the parameterized types are removed. Thus,

Map<String, String> objMap is compiled into Map objMap.

Thus it is composed by keys and object values.This is the reason why groovy code compiles and runs without errors. Hope this helps.

Community
  • 1
  • 1
aces.
  • 3,612
  • 9
  • 36
  • 48