首页 文章

如何获取从Groovy特征继承的属性的java.reflect.Field值?

提问于
浏览
1

我在Grails Web应用程序中使用Groovy 2.4.3 . 我在其中声明了以下Trait / Class层次结构:

trait GuidData {
    String Guid
}

class Enrollment implements GuidData {
    String email
}

当我执行以下代码时,我得到了预期的结果:

Enrollment enrollment = new Enrollment(email: "joe@tester.com", guid: "XXXX")
assert enrollment.properties == ['email':'joe@tester.com', 'guid':'XXXX']
assert enrollment.getProperty("guid") == "XXXX")
Enrollment.getDeclaredField("email") == private java.lang.String Enrollment.email

但是当我执行方法时:

Enrollment.getDeclaredField("guid")

我得到一个NoSuchFieldException . 如果我为“getEmail”方法执行“getDeclaredMethod()”,我正确地得到一个java.reflect.Method实例 .

所以...看起来在特征中定义的Groovy属性显示为Groovy属性,并且可以像在父类中定义的属性一样被引用,但它们不会在标准Groovy属性模式中反映为具有getter / setter的字段 . 换句话说,如果属性出现在对getProperties()的实例调用中,我希望反射调用也可以使Field定义工作 .

1 回答

  • 3

    来自Groovy documentation on Traits,特别是公共领域(如下文Burt所述,这也适用于属性):

    ...为了避免钻石问题,在实施类中重新映射字段名称...

    它继续:

    字段的名称取决于特征的完全限定名称 . 包中的所有点( . )都用下划线(_)替换,最终名称包含双下划线 . 因此,如果字段的类型是String,则包的名称是my.package,特征的名称是Foo,字段的名称是bar,在实现类中,公共字段将显示为:String my_package_Foo__bar .

    因此,对于实现 GuidDataEnrollment 类,它没有名为 Guid 的字段,它有一个名为 GuidData__Guid 的字段(假设 Enrollment 不在包中) . 那's why you'重新体验 NoSuchFieldException . 这应该工作:

    Enrollment.getDeclaredField("GuidData__Guid")
    

    Enrollment 类确实有getter / setter String getGuid()void setGuid(String arg1) ,这就是你可以使用常规属性访问器或使用常规getter语法来访问它的方法 .

相关问题