Groovy Strings n Things
I’d like to take a moment to speculate on one of our previous posts, A quirk in Groovy maps and GString coercion.
This post brought up a good example of some buggy behavior in Groovy when it comes to GStrings and Maps. However, I don’t think the problem is in the Map, but in mixing/matching java.lang.String’s with groovy.lang.GString’s, and in particular on existing Java class methods that expect Strings. Taking the two examples from the previous post..
println map["$aVar"] //still good, this outputs x.
println map.get(”$aVar”) // oh snap! this outputs null!
println ‘a’ == “$aVar” // true
println ‘a’.equals(”$aVar”) // double snap!! it’s false!!
I think there’s a pattern..
In the first part of both of these example, we’re taking advantage of the operator overloading that Groovy provides and mix/matching java.lang.Strings and groovy.lang.GStrings, which seem to play nicely together in those cases. It appears that the GStrings are being evaluated before being coerced into Strings. The coercion must be happening at runtime for the dynamic GString to have it’s $value translated and put into the resulting String.
However, in the later case of both of these examples, we’re calling existing methods on existing Java classes (java.util.Map and java.lang.String). These methods take Strings not GStrings. In these cases, it looks like Groovy still coerces these GStrings into Strings, but my hunch is that it must do so at compile time in order to play nicely with statically typed Java methods on statically typed java objects. This would mean that it wouldn’t have enough information at that time to replace the $aVar with it’s dynamic runtime value and therefore doesn’t know what else to do but use the literal String value.
This is all speculation of course, but this model makes sense of what we’re seeing here. Is there anyone who knows enough about the internals of Groovy to confirm or deny this speculation?