dictionary - 为什么 Map 不适用于 Groovy 中的 GString?

标签 dictionary groovy gstring

使用以下代码段,我无法检索 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给我一个答案。我不会变异任何东西,也不会混合 StringGString .

最佳答案

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/

相关文章:

sql - 从 GString 转义点

python - python 查找字典键中的最大重复值

python - 如何在 Python 中将 JSON 文件目录加载到 Apache Spark

groovy 多行字符串转义所有

java - Groovy 类加载器不会加载 Java 类

groovy - 将 GString 存储在变量中并在运行时求值

python - 如何从每个键的数据帧字典中获取平均值和标准差

python - 在字典中填充字典

docker - 在groovy代码下实现时,文件描述符错误