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

时间:2010-04-17 10:39:42

标签: reflection scala field invoke scala-2.8

请考虑以下代码:

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

建议的方法是什么?

6 个答案:

答案 0 :(得分:6)

正如其他人所提到的,反射方法会返回Object,因此您必须进行投射。您可能更好地使用Scala编译器为字段访问创建的方法,而不必更改私有字段的可见性。 (我甚至不确定名称私有字段是否保证与访问者方法的名称相同。)

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

答案 1 :(得分:4)

getDeclaredFieldjava.lang.Class的方法。

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

您可以在课程getType中使用Field方法获取该类型,但它不会对您有所帮助,因为它会返回Class[_]。鉴于您知道该类型是String,您始终可以使用field.get(foo).asInstanceOf[String]

强制转换返回的值

答案 2 :(得分:1)

AFAIK,反射始终与Object一起使用,您必须自己投射结果。

答案 3 :(得分:0)

看起来不可能做我想做的事情而不用手工尝试所有可能的类型e。克。

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]]
    .
    .
    .

好吧,让我们希望将来会有一种语言可以运作......

答案 4 :(得分:0)

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

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 :(得分:0)

foo.getClass.getDeclaredField("name").getString(foo)

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