【问题标题】:Scala: set a field value reflectively from field nameScala:从字段名称反射地设置字段值
【发布时间】:2009-10-19 16:05:25
【问题描述】:

我正在学习 scala,但不知道如何做到这一点:

我正在 scala 对象和 google appengine 实体之间做一个映射器,所以如果我有这样的类:

class Student {
    var id:Long
    var name:String
}

我需要创建该类的一个实例,在 java 中我会通过它的名称获取字段,然后执行 field.set(object, value) 但我在 scala 中找不到如何执行此操作。

我不能使用 java 反射,因为 Student 的字段被视为私有字段,因此 field.set 会抛出错误。

谢谢

【问题讨论】:

    标签: reflection scala


    【解决方案1】:

    Scala 将“var”变成了一个私有字段,一个 getter 和一个 setter。因此,为了通过使用 String 标识来获取/设置 var,您需要使用 Java 反射来查找 getter/setter 方法。下面是执行此操作的代码 sn-p。请注意,此代码在 Scala 2.8.0 下运行,不存在重复方法名称和错误的处理。

    class Student {
      var id: Long = _
      var name: String = _
    }
    
    implicit def reflector(ref: AnyRef) = new {
      def getV(name: String): Any = ref.getClass.getMethods.find(_.getName == name).get.invoke(ref)
      def setV(name: String, value: Any): Unit = ref.getClass.getMethods.find(_.getName == name + "_$eq").get.invoke(ref, value.asInstanceOf[AnyRef])
    }
    
    val s = new Student
    s.setV("name", "Walter")
    println(s.getV("name"))  // prints "Walter"
    s.setV("id", 1234)
    println(s.getV("id"))    // prints "1234"
    

    【讨论】:

    • 谢谢!这真的很有帮助,我使用了你的一部分代码并在 Scala 2.7.6 中运行良好
    • 如果事先知道方法参数类型,使用getClass.getDeclaredMethod也可以直接按名称取方法!
    • 为什么比设置 field.setAccessible(true) 更好?
    • 您可以通过更改 find 方法定义来使用 javabean。例如,对于 getV 方法:find(_.getName == s"get${lowerCamelToUpperCamel(name)}" 和设置器 find(_.getName == s"set${lowerCamelToUpperCamel(name)}"。当然,您还必须定义一个 lowerCamelToUpperCamel 函数,例如。使用番石榴:def lowerCamelToUpperCamel(str : String) { CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, str)}.
    猜你喜欢
    • 2014-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-16
    • 2019-04-22
    • 1970-01-01
    • 2014-10-07
    • 1970-01-01
    相关资源
    最近更新 更多