使用以下代码段,我无法检索 gString
从 map :
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 map[gString] // Fails
这到底怎么可能?
断言消息清楚地表明 Groovy 存在严重错误:
assert map[gString] // Fails
| ||
| |contents
| null
[contents:true]
这与 Why groovy does not see some values in dictionary? 不是同一个问题
那里的第一个答案表明:
You're adding GString instances as keys in your map, then searching for them using String instances.
在这个问题中,我清楚地添加了
GString
并尝试检索 GString
.也没有 Why are there different behaviors for the ways of addressing GString keys in maps?也不是 Groovy different results on using equals() and == on a GStringImpl给我一个答案。我不会变异任何东西,也不会混合
String
与 GString
.
最佳答案
tl;博士:您似乎在 Groovy 的运行时参数重载评估中发现了一个错误。
答案:map[gString]
被评估为 map.getAt(gString)
在运行时直接通过 Groovy 的运算符重载机制。到目前为止,一切都很好,但现在一切都开始出错了。 Java LinkedHashMap
类(class)没有 getAt
方法在它的类型层次结构中的任何地方,所以 Groovy 必须使用动态关联的 mixin 方法来代替(实际上该语句有点颠倒。Groovy 在使用类层次结构中声明的方法之前使用 mixin 方法。)
因此,长话短说,Groovy 解析 map.getAt(gString)
使用分类方法DefaultGroovyMethods.getAt()
.容易,对吧?除了此方法有大量不同的参数重载,其中一些可能适用,尤其是当您考虑 Groovy 的默认参数强制时。
不幸的是,没有选择 DefaultGroovyMethods.getAt(Map<K,V>,K)
,这似乎是一个完美的匹配,Groovy 选择了 DefaultGroovyMethods.getAt(Object,String)
, 强制 GString
关键参数变成 String
.由于实际 key 实际上是 GString
,该方法最终无法找到该值。
对我来说,真正的杀手是,如果直接从代码中执行参数重载解析(而不是在运算符解析和类别方法选择之后),那么 Groovy 会做出正确的重载选择!也就是说,如果替换这个表达式:
map[gString]
用这个表达:
DefaultGroovyMethods.getAt(map,gString)
然后正确解析参数重载,并找到并返回正确的值。
关于dictionary - 为什么 Map 不适用于 Groovy 中的 GString?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39141245/