Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy GStringImpl and String behaviour

Tags:

I've recently been reading about the behavior of GStringImpls vs Strings when used in collections in Groovy.

I understand that the reason this evaluates to false...

"${'test'}".equals("test") == false

is due to the symmetry requirement of the .equals() contract, however I was wondering if there was a reason the GStringImpl couldn't just be evaluated to a String immediately. So when I do something like this...

"${'someString'}"

I don't get a GStringImpl, I just get a plain Java String back, which I can immediately use as the key in a map, for example.

I know there are some workarounds, like

String s = "${'someString'}"

however stuff like this is a bit inconvenient, and the mix-up between GStringImpl and String seems to be a big 'gotcha' for Groovy newbies.

like image 910
rcgeorge23 Avatar asked Sep 24 '13 07:09

rcgeorge23


1 Answers

GStrings are not evaluated inmediately to String because of some reasons, mainly related to lazy evaluation (which is quite good for logging) and templating. In Strings and GString you can find a good explanation:

GString can involve lazy evaluation so it's not until the toString() method is invoked that the GString is evaluated. This lazy evaluation is useful for things like logging as it allows the calculation of the string, the calls to toString() on the values, and the concatenation of the different strings to be done lazily if at all.

GString is pretty handy when you don't want to use a template engine, or when you really want full lazy evaluation of GStrings. When some variable embedded in a GString, the toString() is called on that variable to get a string representation, and it's inserted into the final string.

Therefore:

GString and String are two distinct classes, and hence use of GString objects as keys for Map objects or comparisons involving GString objects, can produce unexpected results when combined with String objects since a GString and a String won't have the same hashCode nor will they be equal. There is no automatic coercion between the two types for comparisons or map keys, so it's sometimes necessary to explicitly invoke toString() on GString objects.

Unexpected conversion to String can lead to problems when code is expecting a GString, as for methods in groovy.sql classes.

like image 130
jalopaba Avatar answered Sep 25 '22 20:09

jalopaba