Groovy中[:]创建的Map访问.class属性返回null的原因
问题说明
我了解到Groovy会使用java.util.ArrayList作为数组字面量(例如arr = [])创建对象的底层实现类。我希望明确通过my_map = [:]这种Map字面量语法创建的对象,Groovy底层采用的是什么实现类,因此编写了如下测试代码:
array = [] array[1] = 'a' array[2] = 'b' println array.class.name println array my_map = [:] my_map['OK'] = 200 println my_map.class println my_map
上述代码的运行输出结果如下:
java.util.ArrayList [null, a, b] null [OK:200]
从输出可以看到,my_map实例访问.class属性时返回了null,请问出现该现象的原因是什么?
回答
这是Groovy对Map类型的属性访问做的特殊语法处理导致的,和Map本身的实现类没有关系:
- 对List这类非Map的普通对象,
对象.xxx的写法会走标准的对象属性访问逻辑,自动匹配对象的公开字段或者对应getter方法,所以示例里array.class能正常调用getClass(),拿到java.util.ArrayList的类对象。 - 但所有Map实例用
map.xxx写法的时候,Groovy 不会访问Map对象自身的属性和方法,而是直接把点后面的名字当成Map的key,等价于执行map.get('xxx'),去键值对集合里找对应的值。你的代码里从来没给my_map存过key为class的条目,返回null完全符合预期。
补充两个相关的知识点:
[:]声明的空Map默认底层实现是java.util.LinkedHashMap,会保留键值对的插入顺序。- 要正确拿到Map实例本身的Class对象,别用
.class的简写,两种写法可以避开语法拦截:- 显式调用方法:
my_map.getClass() - 用Groovy的直接属性访问符
.@绕过键查找逻辑:my_map.@class
执行后都会正确输出class java.util.LinkedHashMap。
- 显式调用方法:
验证小技巧:往map里存一条
my_map['class'] = '我是存进去的值',再执行println my_map.class,输出的就是你存的字符串,根本不会返回类对象,刚好能印证这个语法规则。
内容的提问来源于stack exchange,提问作者sshekhar
相关产品推荐
相关产品推荐

