2010-04-17 64 views
10

考慮下面的代碼:如何通過反射來訪問一個字段的值(斯卡拉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)。

建議如何做到這一點?

回答

0

看起來這是不可能的做我想做什麼用了嘗試所有可能的手工類型e。 G。

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

好了,讓我們希望會出現在未來,像這樣的作品語言...

3

getDeclaredFieldjava.lang.Class的方法。

您必須將foo.getDeclaredField("name")更改爲foo.getClass.getDeclaredField("name")(或classOf[Foo].getDeclaredField("name"))以獲取該字段。

您可以使用類Field中的getType方法獲得類型,但它不會幫助您,因爲它返回Class[_]。給出比你知道的類型是一個字符串,你總是可以使用field.get(foo).asInstanceOf[String]

+0

我修復了丟失的getClass,這只是一個疏忽。 我不知道如何在不知道事先知道的情況下進行演員表演。如果我知道我需要處理的課程,我不需要反思...... 感謝您的建議! – soc 2010-04-17 16:03:21

+0

你可以使用類似'value match {case s:String =>/*對某個字符串做某事*/case _ =>/*執行其他操作* /}'來匹配對象。不知道我是否明白你想要做什麼。 – gerferra 2010-04-19 15:58:34

1

返回的值。

+0

是的,我誤解了這個問題,現在我改變了mi的答案。 – gerferra 2010-04-17 13:25:52

5

正如其他人所說,反射方法返回Object,所以你必須施放。您可能會更好地使用Scala編譯器爲字段訪問創建的方法,而不必更改專用字段的可見性。 (我甚至不知道名字的私人領域是保證相同的訪問方法。)

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

與** foo.getClass.getDeclaredField(「name」)**配合良好,因爲foo.getClass.getDeclaredMethod沒有名爲* get * – Kruser 2017-10-17 12:26:17

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