Dictionary 为什么我不能得到与Groovy中映射的GString完全相同的GString?

Dictionary 为什么我不能得到与Groovy中映射的GString完全相同的GString?,dictionary,groovy,gstring,Dictionary,Groovy,Gstring,使用以下代码段,我无法从映射中检索gString: def contents = "contents" def gString = "$contents" def map = [(gString): true] assert map.size() == 1 // Passes assert gString.hashCode() == map.keySet().first().hashCode() // Passes, same hash code assert gString.is(map.

使用以下代码段,我无法从映射中检索
gString

def contents = "contents"
def gString = "$contents"

def map = [(gString): true]

assert map.size() == 1 // Passes
assert gString.hashCode() == map.keySet().first().hashCode() // Passes, same hash code
assert gString.is(map.keySet().first()) // Passes, exactly the same object
assert map[gString] // Fails
这怎么可能?

这里有趣的是,
map.get(map.keySet()[0])
工作正常,而
map.get[map.keySet()[0]]
工作不正常

断言消息清楚地表明存在错误:

assert map[gString] // Fails
       |  ||
       |  |contents
       |  null
       [contents:true]
这和我的问题不一样 第一个答案是:

您将GString实例添加为地图中的键,然后使用字符串实例搜索它们

在这个问题中,我清楚地添加了
GString
,并尝试检索
GString


我也没有答案。我不会变异任何东西,也不会将
String
GString
混合使用。也没有帮助。

tl;dr:您似乎在Groovy的运行时参数重载计算中发现了一个错误

回答:

map[gString]
在运行时通过Groovy的操作符重载机制直接计算为
map.getAt(gString)
。到目前为止,一切都很好,但现在一切都开始出错了。Java
LinkedHashMap
类在其类型层次结构中的任何位置都没有
getAt
方法,因此Groovy必须使用动态关联的mixin方法(实际上该语句有点颠倒。Groovy在使用类层次结构中声明的方法之前使用mixin方法)

因此,长话短说,Groovy解析
map.getAt(gString)
使用category方法
DefaultGroovyMethods.getAt()
。很简单,对吧?除了此方法有大量不同的参数重载,其中一些可能适用,特别是在考虑Groovy的默认参数强制时

不幸的是,Groovy没有选择似乎是完美匹配的
DefaultGroovyMethods.getAt(Map,K)
,而是选择了
DefaultGroovyMethods.getAt(Object,String)
,这将
GString
键参数强制为
字符串。由于实际键实际上是一个
GString
,因此该方法最终无法找到值

对我来说,真正的杀手是,如果参数重载解析直接从代码中执行(而不是在运算符解析和类别方法选择之后),那么Groovy会做出正确的重载选择!也就是说,如果替换此表达式:

map[gString]
DefaultGroovyMethods.getAt(map,gString)
用这句话:

map[gString]
DefaultGroovyMethods.getAt(map,gString)

然后正确地解决了参数重载问题,找到并返回了正确的值。

这是一个很好的问题,也许您应该在票据中添加
map.get[map.keySet()[0]]
不起作用,但
map.get(map.keySet()[0])
效果很好。@Vampire谢谢,编辑的问题-确实非常有趣,只需添加doing
map[gString]=1生成了这个有趣的地图
[内容:true,内容:1]
。几乎就好像
getAt
/
putAt
使用gstring的字符串表示法一样……请参见我对您的(被错误地忽略的)问题的评论:。你似乎发现了一个合法的bug。Groovy运行时似乎在动态地将
map[gString]
映射到
DefaultGroovyMethods.getAt()
的错误重载。