代码之家  ›  专栏  ›  技术社区  ›  soc Bhuwan Tripathi

如何通过反射访问字段值(scala 2.8)

  •  12
  • soc Bhuwan Tripathi  · 技术社区  · 15 年前

    请考虑以下代码:

    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,但没有字符串。基本上,我需要正确的类型,因为我想对它调用一个方法(例如tochararray)。

    建议的方法是什么?

    5 回复  |  直到 8 年前
        1
  •  6
  •   Ben Lings    10 年前

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

    val foo = new Foo
    val method = foo.getClass.getDeclaredMethod("name")
    val value = method.get(foo).asInstanceOf[String]
    
        2
  •  4
  •   gerferra    15 年前

    getDeclaredField 是一种方法 java.lang.Class .

    你得换衣服 foo.getDeclaredField("name") foo.getClass.getDeclaredField("name") (或) classOf[Foo].getDeclaredField("name") )去拿场地。

    你可以用 getType 课堂教学法 Field 但它不会帮助你,因为它会回来 Class[_] . 如果不知道类型是字符串,则始终可以使用 field.get(foo).asInstanceOf[String]

        3
  •  1
  •   Daniel C. Sobral    15 年前

    阿法克,反射总是与对象一起工作,你必须自己投射结果。

        4
  •  0
  •   soc Bhuwan Tripathi    15 年前

    看起来这是不可能做到我想用手尝试所有可能的类型,例如。

    o match {
        case I  if o.isInstanceOf[Int] => val i = I.asInstanceOf[Int] 
        case F  if o.isInstanceOf[Float] => val f = I.asInstanceOf[Float] 
        case S  if o.isInstanceOf[String] => val s = I.asInstanceOf[String] 
        case OF if o.getGenericType.toString == "scala.Option<java.lang.Float>" => val of = OF.asInstanceOf[Option[Float]]
        .
        .
        .
    

    好吧,让我们希望将来会有一种语言,像这样的语言可以工作…

        5
  •  0
  •   Sruthi Poddutur    8 年前

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

    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)
        }
    }