我有一个用其他字符串制作的 groovy 字符串,例如:
def final PREFIX = "myprefix"
def prefix2 = PREFIX + ".whatever1"
现在假设我有一个HashMap
我想使用 prefix2
进行查找作为 key 的一部分:
HashMap<String,String> map = new HashMap<String,String>()
map.put("myprefix.whatever1.value","aaa")
如果我这样做:
def key = "${prefix2}.value"
String result=(map.get(key))
然后result = null
,但如果我这样做:
String key="${prefix2}.value"
String result=(map.get(key))
然后result = aaa
.
我可以理解为什么会发生这种情况,显然是类型推断问题。但我仍然觉得这让我感到恶心。有些东西就是“感觉不太对劲”。你明白我的意思吗?
这种事情正常吗?应该是“预料之中的”吗?我是否对 Groovy 要求太多了,让 Groovy 知道如果我使用引号创建了字符串,那么它在用于查找 Hashmap <String, String>
中的值时应该可以工作。而不被定义为 String
对象引用?这是错误还是功能?
最佳答案
为什么会发生这种情况,需要考虑多种因素。
当您创建变量 HashMap<String,String> map
时您可能会期望像在 java 中一样,您只能将字符串作为键和值添加到其中。 groovy 中的情况并非如此,因为不会考虑类型参数,这意味着以下内容将起作用:
HashMap<String,String> map = new HashMap<String,String>()
map.put(1, 2)
assert map.get(1) == 2
assert map.get(1) instance of Integer
正如您所说,像 "${prefix2}.value"
这样的内插字符串是 GString
的一个实例(具体来说是GStringImpl
)所以以下是正确的
def key = "${prefix2}.value"
assert key instanceof GString
所以,map.get(key)
将会被 GString
调用参数没有错误,因为字符串约束已被删除,如果 GStringImpl
则这不会成为问题。将给出与 String
相同的哈希码,但事实并非如此
assert key == "myprefix.whatever1.value"
assert key.hashCode() != "myprefix.whatever1.value".hashCode()
这就是为什么 map 上的 get 返回 null
解决这个问题的方法是,正如您使用 toString()
所说的那样或将 GString 分配给 String 变量( toString()
被隐式调用)
我更喜欢的另一种方法是不要将通常的 java 风格的 map 访问与 groovy 的 map 访问混合起来。如果您使用 GString 在 map 上索引的属性符号或键,它将完美地工作:
def final PREFIX = "myprefix"
def prefix2 = PREFIX + ".whatever1"
// def map = [:] // shorter will be a LinkedHashMap
HashMap<String,String> map = [:] as HashMap // if you really need HashMap
map."myprefix.whatever1.value" = "aaa"
def key = "${prefix2}.value"
assert map[key] == "aaa"
assert map."${prefix2}.value" == "aaa"
assert map."$key" == "aaa"
关于java - Groovy 字符串与 Java 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39045417/