2013-04-24 37 views
2

工作,我宣佈一個類:階反射不能在這種情況下

trait TO { 
    @BeanProperty var id: String = _ 
    @BeanProperty var age : Int = _  
    @BeanProperty var createdAt : Long = _ 
    @BeanProperty var disable: Boolean = _ 
} 
class UMTTestObject extends TO { 
    @BeanProperty var inner: UMTInnerTO = _ 
} 
class UMTInnerTO extends TO{} 

並在反思,這不適合UMTInnerObject的setAge工作:

setter.invoke(inner, 0) 

而二傳手是UMTInnerObject的setAge,內是UMTInnerObject

的實例的錯誤味精所示:

的java。 lang.NoSuchMethodError:me.baihe.blackhole.luna.helpers.TO $ class.setAge(LME /白河/黑洞/盧納/助理/ TO;我)V

這是非常puzzle--

任何人知道爲什麼?

+0

看來你正在處理Java Reflection API。我鼓勵你閱讀Scala反射文檔,特別是這個[部分](http://docs.scala-lang.org/overviews/reflection/overview.html#accessing_and_invoking_members_of_runtime_types),以便學習如何設置一個值改爲使用Scala Reflection API。 – jeslg 2013-04-24 11:36:36

+0

你能提供更多的細節嗎?例如,你如何獲得'setter'? – ghik 2013-04-24 12:57:36

+0

@JesúsLópez-González,所以你認爲scala不能使用java反射API,因爲兼容性? – user1453345 2013-04-25 03:32:22

回答

2

這REPL會話展示瞭如何可以使用Scala的反射API調用設置:

scala> import scala.reflect.runtime. { universe => ru } 
import scala.reflect.runtime.{universe=>ru} 

scala> trait TO { var age: Int = _ } 
defined trait TO 

scala> class UMTInnerTO extends TO 
defined class UMTInnerTO 

scala> val inner = new UMTInnerTO 
inner: UMTInnerTO = [email protected] 

scala> val m = ru.runtimeMirror(inner.getClass.getClassLoader) 
m: reflect.runtime.universe.Mirror ... 

scala> val im = m.reflect(inner) 
im: reflect.runtime.universe.InstanceMirror = instance mirror for [email protected] 

scala> val setterSymb = (ru.typeOf[UMTInnerTO].members find (_.name.decoded == "age_=")).get 
setterSymb: reflect.runtime.universe.Symbol = method age_= 

scala> val setter = im.reflectMethod(setterSymb.asMethod) 
setter: reflect.runtime.universe.MethodMirror = method mirror for TO.age_$eq(x$1: scala.Int): scala.Unit (bound to [email protected]) 

scala> inner.age 
res0: Int = 0 

scala> setter(5) 
res1: Any =() 

scala> inner.age 
res2: Int = 5 

您可以訪問Scala Reflection Documentation瞭解什麼是在片段發生。

-

修訂:無論如何,如果你仍然有興趣在Java API中,我們開始吧!

你應該知道setter斯卡拉不使用Java命名約定。您不會找到setAge方法(至少,如果您不手動聲明它)。相反,您必須搜索age_=方法。

scala> classOf[UMTInnerTO].getMethod("age_$eq", classOf[Int]) 
res0: java.lang.reflect.Method = public void UMTInnerTO.age_$eq(int) 

scala> inner.age 
res1: Int = 0 

scala> res0.invoke(inner, 3: Integer) 
res2: Object = null 

scala> inner.age 
res3: Int = 3 

這個post對吸氣劑和二道板有幫助。

+0

謝謝。我已閱讀過之前的scala反射api :)我認爲scala api有點複雜。我只想讓setter和getter方法調用普通類 – user1453345 2013-04-25 03:32:55

+0

但是我爲每個字段添加@BeanProperty。我確實得到setAge – user1453345 2013-04-27 05:16:57

+0

的setter我發現這個問題並不是那麼明顯,因爲如果我在REPL中執行代碼,它會起作用。所以我認爲這可能是scala中的一個隱藏的bug。我會進一步挖掘 – user1453345 2013-04-27 05:22:42