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