【问题标题】:How do I get a java.reflect.Field value for a property inherited from a Groovy trait?如何获取从 Groovy 特征继承的属性的 java.reflect.Field 值?
【发布时间】:2016-08-30 11:55:31
【问题描述】:

我在 Grails Web 应用程序中使用 Groovy 2.4.3。我在其中声明了以下特征/类层次结构:

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 实例。

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

【问题讨论】:

  • 你的意思是Enrollment.getDeclaredField("guid") 抛出NoSuchFieldException
  • 是的。 Enrollment.getDeclaredField("guid") 抛出 NoSuchFieldException。

标签: grails reflection groovy traits


【解决方案1】:

来自Groovy documentation on Traits,特别是在公共字段上(如下 Burt 所述,这也适用于属性):

...为了避免diamond problem,字段名称在实现类中重新映射...

继续:

字段的名称取决于特征的完全限定名称。包中的所有点 (.) 都替换为下划线 (_),并且最终名称包含双下划线。所以如果字段的类型是String,包的名字是my.package,trait的名字是Foo,字段的名字是bar,在实现类中,公共字段会出现为:@987654323 @。

所以对于实现GuidDataEnrollment 类,它没有名为Guid 的字段,它有一个名为GuidData__Guid 的字段(假设Enrollment 不在包中)。这就是您遇到NoSuchFieldException 的原因。这应该有效:

Enrollment.getDeclaredField("GuidData__Guid")

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

【讨论】:

  • 这不是一个公共字段,它是一个属性。但是属性的字段(例如String foo)和声明的公共字段(例如public String foo)同样被重命名
  • 呃。我的错,感谢@BurtBeckwith 的澄清
  • 好的……这很有意义并且有效。当使用反射来获取对象中所有字段的数据类型时,这会带来一个有趣的难题基类实现并合成每个查找名称以获得字段定义。如果你有多重继承,那么我想知道你怎么知道哪一个绑定到了在实现类上显示 properties() 方法的属性名称?
  • 谢谢,很高兴知道。我使用以下方法从特征中反射性地查找属性的字段:``` domainClass.clazz.getDeclaredFields().find { field -> field.getName().endsWith('__' + propertyName) } ```跨度>
猜你喜欢
  • 1970-01-01
  • 2013-12-16
  • 2014-08-10
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多