简短
我需要通过键的动态名称对map/property进行空值安全访问。Map本身可以为空值。我已经想到了map?.(keyName)
,但不知道为什么它不能像预期的那样工作,总是返回null
代码示例
def map = [key: 'value']
def keyName = 'key'
map.each({ key, value -> println("[${key.class}]: [${value.class}]")})
println("keyName class is [${keyName.class}]")
println(map?.(keyName)) // null <--------- My question
// Alternatives that work well
println(map?.(keyName as String)) // value
println(map?.(keyName as java.lang.String)) // value
println(map?.get(keyName)) // value
- 输出 *
[class java.lang.String]: [class java.lang.String]
keyName class is [class java.lang.String]
null
value
value
value
问题
如果keyName
和Map键都是java.lang.String
类型,为什么map?.(keyName)
不返回值?为什么map?.(keyName as String)
返回值?
3条答案
按热度按时间j2qf4p5b1#
圆括号只是控制计算的优先级。对于
(keyName)
,圆括号中没有要计算的内容,因此圆括号没有意义,map?.(keyName)
与map?.keyName
相同,即map?.get('keyName')
。对于
map?.(keyName as String)
,括号中有一些要计算的内容,因此它首先进行计算,并解析为map?.'key'
,即map?.get('key')
。如果你想使用一个动态键值,你必须确保它是由某个表达式来计算的。各种选择(有些你已经找到了)包括:
map?.(keyName as String)
map?.get(keyName)
map?."$keyName"
map[keyName]
个虽然最后一个选择不是
null
-当然关于Map更安全。我个人更喜欢第三种方法。您可能想知道为什么
def map = [(keyName): 'value']
可以使用keyName
的值作为键,而map?.(keyName)
不能使用keyName
的值进行检索,但是原因很简单。2点标记法只适用于字符串键。3用括号定义的Map适用于任何对象类型。所以当你用括号中的键定义一个Map时,你可以使用任何Object作为键,但是你只能从一个带有点标记的String键的Map中提取对象,因此这里关于括号的语义是不同的。z8dt9xmd2#
Groovy将
map?.(keyName)
解析为map?.get('keyName')
。使用map?.keyName
会产生相同的结果:qyuhtwio3#
正如@吸血鬼所指出的
用于检索的点标记法仅适用于String键
但是在我的例子中,我需要动态地设置key,而它不是字符串key。所以我最终的解决方案是遍历map,直到我找到我的key部分: