Как получить доступ к значению поля через отражение (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).

Каков предложенный способ сделать это?

Ответ 1

Похоже, что невозможно сделать то, что я хочу, пробовать все возможные типы вручную. г.

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

Ну, пусть надеется, что в будущем будет язык, где что-то подобное работает...

Ответ 2

Как уже упоминалось, методы отражения возвращают Object, поэтому вам нужно бросить. Возможно, вам лучше использовать метод, который компилятор Scala создает для доступа к полю, вместо того, чтобы изменять видимость частного поля. (Я даже не уверен, что имя частного поля гарантировано будет таким же, как и у методов доступа.)

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

Ответ 3

getDeclaredField является методом java.lang.Class.

Вам нужно изменить foo.getDeclaredField("name") на foo.getClass.getDeclaredField("name") (или classOf[Foo].getDeclaredField("name")), чтобы получить поле.

Вы можете получить тип с методом getType в классе Field, но он вам не поможет, потому что он возвращает Class[_]. Если вы знаете, что тип - это String, вы всегда можете вернуть значение, возвращенное с помощью field.get(foo).asInstanceOf[String]

Ответ 4

AFAIK, рефлексия всегда работает с Object, и вы должны сами делать результаты.

Ответ 5

Вот как можно получить список имен полей и его значение класса 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)
    }
}