Groovy GString通过接口引用变量时插值为null异常问题
问题原因
这个问题是Groovy遵循Java接口字段规范导致的:
- 所有在Java/Groovy接口中直接声明的字段,默认修饰符都是
public static final,属于接口的静态常量,而非对实现类需要包含的实例属性的约定。你定义的PublicBinary接口中byte[] bytes、String publicKey、Person person三行本质是声明了三个静态常量,且因为你没有赋值,这三个常量的默认值就是null。 - 当你将变量声明为
PublicBinary接口类型时,Groovy的动态属性访问逻辑(GString插值取值时默认调用该逻辑)会优先匹配接口的静态成员,因此直接返回了接口静态常量的null值,而不会去读取实现类的实例属性。当变量声明为实现类AdditionalPhoto类型时,没有对应的静态常量,Groovy会直接匹配实例属性的getter方法,因此取值正常。
解决方案
最优方案(推荐)
修改接口定义,将原本的字段声明改为对应getter方法声明,明确约定实现类需要提供的实例属性:
interface PublicBinary { byte[] getBytes() String getPublicKey() Person getPerson() }
Groovy的实现类中已经自动生成了对应属性的getter方法,不需要修改实现类代码,修改后用接口类型的变量做GString插值就可以正常取值。
临时兼容方案
如果不方便修改接口定义,可以在插值时显式调用getter方法,绕过动态属性的静态匹配逻辑:
将插值写法从"${binary.publicKey}"改为"${binary.getPublicKey()}"即可正常取值。
内容的提问来源于stack exchange,提问作者SGT Grumpy Pants
相关产品推荐
相关产品推荐

