Groovy陷阱:字符串插值在list.contains()中未执行的原因及解决方案
问题底层原理
这个现象完全是Groovy中GString类型的懒加载特性导致的,核心逻辑如下:
- 你用
"${变量}"语法生成的字符串默认不是Java原生String类型,而是Groovy独有的GString实现类,它不会在定义时就直接把占位符替换成实际值,只会在需要输出成字符串形式的场景才会触发插值计算。 GString重写了Groovy的==比较逻辑:当你用==把GString和String对比时,Groovy会先主动触发GString的插值,把两者都转成字符串内容再对比,所以你写的自定义相等判断方法能返回true。- 但Java标准库的
List.contains()方法底层调用的是Object原生的equals()方法,且Java原生方法不会识别Groovy的GString特殊逻辑:GString的equals()方法和String的equals()逻辑不兼容,就算GString插值后的内容和目标String完全一致,两者调用equals()也会返回false,这就是你调用contains()匹配失败的根本原因。 - 你看到println输出targ是正确值,只是因为println会调用对象的
toString()方法,触发了GString的插值,但这个操作不会改变GString对象本身的类型,也不会预存插值后的结果,后续调用contains()还是会拿原GString对象去做equals比较,自然还是失败。 - 你显式强转成
String、或者用new String()包裹插值语句的写法,本质是强制在定义时就触发GString的插值,把它直接转成Java原生String类型,后续所有比较逻辑都走普通字符串的规则,自然就能匹配成功。
最佳实践
所有需要和Java标准库交互、或者需要做集合匹配的插值字符串,在定义时就显式声明为String类型,写法为:
String targ = "${TARGET_DATA}"
内容的提问来源于stack exchange,提问作者tk-noodle
相关产品推荐
相关产品推荐

