2013-04-24 71 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