使用以下代码段,我无法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 map[gString] // Fails
那到底怎么可能呢?
断言消息清楚地表明Groovy存在严重错误:
assert map[gString] // Fails
| ||
| |contents
| null
[contents:true]
这与为什么Groovy在字典中看不到某些值的问题不同?那里的第一个答案表明:
您正在将GString实例添加为地图中的键,然后使用String实例搜索它们。
在这个问题中,我明确地添加GString
并尝试检索GString
。
同样,为什么在映射GString键的方式上没有不同的行为呢?也没有在GStringImpl上使用equals()和==的Groovy不同结果对我有答案。我不会变异任何东西,也不会String
与混淆GString
。
tl; dr:您似乎在Groovy的运行时参数重载评估中发现了一个错误。
回答:
map[gString]
map.getAt(gString)
通过Groovy的运算符重载机制可以在运行时直接进行评估。到目前为止,一切都很好,但是现在一切都开始变糟了。JavaLinkedHashMap
类getAt
在其类型层次结构中的任何地方都没有方法,因此Groovy必须改为使用动态关联的mixin方法(实际上,该语句有点相反。Groovy在类层次结构中使用已声明的方法之前先使用mixin方法。)
因此,总而言之,Groovy决心map.getAt(gString)
使用category方法DefaultGroovyMethods.getAt()
。轻松自在,对不对?除了此方法具有大量不同的参数重载之外,其中一些可能适用,尤其是当您考虑Groovy的默认参数强制时。
不幸的是,DefaultGroovyMethods.getAt(Map<K,V>,K)
Groovy并未选择似乎是完美的选择,而是选择了将关键参数DefaultGroovyMethods.getAt(Object,String)
强制GString
转换为String
。由于实际的密钥实际上是a GString
,因此该方法最终无法找到该值。
对我而言,真正的杀手is是,如果直接从代码中执行参数重载解析(而不是在运算符解析和类别方法选择之后执行),那么Groovy会做出正确的重载选择!也就是说,如果替换此表达式:
map[gString]
带有以下表达式:
DefaultGroovyMethods.getAt(map,gString)
然后正确地解析了参数重载,并找到并返回了正确的值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句