Как получить доступ к значению поля с помощью отражения (Scala 2.8) - PullRequest
12 голосов
/ 17 апреля 2010

Рассмотрим следующий код:

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

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

Ответы [ 5 ]

6 голосов
/ 17 апреля 2010

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

val foo = new Foo
val method = foo.getClass.getDeclaredMethod("name")
val value = method.get(foo).asInstanceOf[String]
4 голосов
/ 17 апреля 2010

getDeclaredField - это метод java.lang.Class.

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

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

1 голос
/ 17 апреля 2010

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

0 голосов
/ 22 сентября 2017

Вот как можно получить список имен полей и его значение для класса дела:
Сначала, используя отражение, получаем информацию о полях следующим образом -

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)
    }
}
0 голосов
/ 20 апреля 2010

Похоже, что невозможно делать то, что я хочу, без попытки всех возможных типов вручную 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]]
    .
    .
    .

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

...