【问题标题】:How to access a field's value via reflection (Scala 2.8)如何通过反射访问字段的值(Scala 2.8)
【发布时间】:2011-02-09 03:01:54
【问题描述】:

考虑以下代码:

class Foo(var name: String = "bar")

现在我尝试通过反射来获取它的值和正确的类型:

val foo = new Foo
val field = foo.getClass.getDeclaredField("name")
field.setAccessible(true)
//This is where it doesn't work
val value = field.get(????)

我尝试了 field.get(foo) 之类的方法,但它只返回一个 java.lang.Object 而没有 String。基本上我需要正确的类型,因为我想在它上面调用一个方法(例如 toCharArray)。

建议的方法是什么?

【问题讨论】:

    标签: reflection scala field invoke scala-2.8


    【解决方案1】:

    getDeclaredFieldjava.lang.Class 的一个方法。

    您必须将foo.getDeclaredField("name") 更改为foo.getClass.getDeclaredField("name")(或classOf[Foo].getDeclaredField("name"))才能获得该字段。

    您可以在Field 类中使用getType 方法获取类型,但这对您没有帮助,因为它返回Class[_]。鉴于您知道类型是 String,您始终可以使用 field.get(foo).asInstanceOf[String] 转换返回的值

    【讨论】:

    • 我修复了丢失的 getClass,这只是一个疏忽。我想知道如何在事先不知道它是什么的情况下进行演员表。如果我知道我必须处理的课程的所有内容,我就不需要反思......感谢您的建议!
    • 您可以将对象与 value match { case s: String => /* do something with a string */ case _ => /* do something else */ } 之类的内容进行模式匹配。不知道我是否明白你想要做什么。
    【解决方案2】:

    AFAIK,反射总是与 Object 一起工作,你必须自己投射结果。

    【讨论】:

    • 是的,我误解了这个问题,现在我改变了答案。
    【解决方案3】:

    正如其他人所提到的,反射方法返回Object,所以你必须强制转换。最好使用 Scala 编译器为字段访问创建的方法,而不必更改私有字段的可见性。 (我什至不确定名称私有字段是否保证与访问器方法的名称相同。)

    val foo = new Foo
    val method = foo.getClass.getDeclaredMethod("name")
    val value = method.get(foo).asInstanceOf[String]
    

    【讨论】:

    • foo.getClass.getDeclaredField("name") 配合得很好,因为 foo.getClass.getDeclaredMethod 没有名为 get 的成员跨度>
    【解决方案4】:

    这是获取字段名列表及其案例类值的方法:
    首先,使用反射,获取字段信息如下 -

    val TUPLE2_OF_FIELDNAME_TO_GETTERS = typeOf[<CLASS>].members
    .filter(!_.isMethod)
    .map(x => (x.name.toString, classOf[<CLASS>].getDeclaredMethod(x.name.toString.trim)))
    

    怎么用?

    getFieldNameAndValue(obj: <CLASS>): Seq[(String, String)] {
      var output = Seq[(String, String)]()
     for(fieldToGetter <- TUPLE2_OF_FIELDNAME_TO_GETTERS) {
          val fieldNameAsString = fieldToGetter._1
          val getter = fieldToGetter._2
          val fieldValue = getter.invoke(obj).toString
          output += (fieldName, fieldValue)
        }
    }
    

    【讨论】:

      【解决方案5】:
      foo.getClass.getDeclaredField("name").getString(foo)
      

      如果你想避免asInstanceOf,应该可以。 get* 适用于多种类型

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-18
        • 1970-01-01
        • 1970-01-01
        • 2015-07-08
        • 1970-01-01
        • 1970-01-01
        • 2011-04-03
        • 2023-03-31
        相关资源
        最近更新 更多