Groovy GStringImpl and String behaviour

2019-02-08 08:00发布

I've recently been reading about the behaviour 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 mixup between GStringImpl and String seems to be a big 'gotcha' for Groovy newbees.

1条回答
仙女界的扛把子
2楼-- · 2019-02-08 08:40

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.

查看更多
登录 后发表回答