为什么通过括号中的变量访问groovy map始终返回null?

inv*_*nit 2 groovy dictionary

简要

我需要通过密钥的动态名称对映射/属性进行空安全访问.Map本身可以为null.我想出了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

?
Run Code Online (Sandbox Code Playgroud)

产量

[class java.lang.String]: [class java.lang.String]
keyName class is [class java.lang.String]
null
value
value
value
Run Code Online (Sandbox Code Playgroud)

如果两者keyName和地图键都是类型,java.lang.String为什么map?.(keyName)不返回值?为何map?.(keyName as String)回归?

链接

检查Groovy Web控制台

Vam*_*ire 5

括号只是控制评估的优先级.有了(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对地图当然不安全.我个人更喜欢第三种方法.

您可能想知道为什么def map = [(keyName): 'value']使用keyNameas键的值,但map?.(keyName)不能用于使用for的值keyName,但原因很简单.检索的点符号仅适用于String键.使用括号定义地图适用于任何对象类型.因此,在使用括号中的键定义地图时,您可以使用任何Object作为键,但是您只能使用带有点符号的String键从地图中提取对象,因此这里的语义与括号的语义不同.