26

我最近一直在阅读有关GStringImpls 与Strings 在 Groovy 中的集合中使用时的行为。

我知道这评估为假的原因......

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

是由于.equals()合同的对称性要求,但是我想知道是否有原因GStringImpl不能String立即评估为 a 。所以当我做这样的事情时......

"${'someString'}"

我没有得到 a GStringImpl,我只是得到了一个普通的 Java String,例如,我可以立即将其用作地图中的键。

我知道有一些解决方法,比如

String s = "${'someString'}"

然而,这样的事情有点不方便,而且对于 Groovy 新手来说, 和 之间的混淆GStringImpl似乎String是一个很大的“陷阱”。

4

1 回答 1

33

由于某些原因, GString不会立即评估为 String,主要与惰性评估(这对日志记录非常好)和模板有关。在Strings 和 GString你可以找到一个很好的解释:

GString可能涉及惰性求值,因此直到调用 toString() 方法才对 GString 求值。这种惰性求值对于诸如日志记录之类的事情很有用,因为它允许计算字符串、对值的 toString() 调用以及不同字符串的连接(如果有的话)。

当您不想使用模板引擎,或者当您真的想要对 GString 进行完全惰性求值时,GString 非常方便。当某个变量嵌入到 GString 中时,对该变量调用 toString() 以获取字符串表示形式,并将其插入到最终字符串中。

所以:

GString 和 String 是两个不同的类,因此使用 GString 对象作为 Map 对象的键或涉及 GString 对象的比较,在与 String 对象结合时会产生意想不到的结果,因为 GString 和 String 不会有相同的 hashCode 也不会等于。对于比较或映射键,两种类型之间没有自动强制转换,因此有时需要在 GString 对象上显式调用 toString()。

当代码需要 GString 时,意外转换为 String 可能会导致问题,就像 groovy.sql 类中的方法一样。

于 2013-09-24T08:32:22.633 回答