使用Int参数进行Scala反射

时间:2016-09-16 09:58:14

标签: scala reflection

在下面的代码中,我尝试调用一个具有Int参数的对象方法(给它一个值3)。这会返回Int3不兼容类型的错误。

//Using scala's Int does not work!
object MyObject{
  def handleInt(id:Int) : Boolean = {
    true
  }
}

object testApp extends App {
    val obj    = MyObject.getClass
    val method = obj.getDeclaredMethod("handleInt", classOf[Int]) //Int.getClass shows the same behavior
    val rsp    = method.invoke(obj, 3)
}
  

错误:(106,41)隐式转换的结果类型必须更多   特定于AnyRef

    val rsp    = method.invoke(obj, 3)
     

错误:(106,41)类型不匹配;发现:Int(3)required:Object

    val rsp    = method.invoke(obj, 3)

我尝试在这里修改很多东西,唯一可行的方法是将所有签名更改为Java Integer。代码如下所示:

//This works with Java's Integer
object MyObject{
  def handleInt(id:Integer) : Boolean = {
    true
  }
}

object testApp extends App {
    val obj    = MyObject.getClass
    val method = obj.getDeclaredMethod("handleInt", classOf[Integer])
    val rsp    = method.invoke(obj, 3)
}

我的问题是:

  1. 有人可以解释为什么会这样吗?我认为 scala的Int包裹了java的原始int(这就是为什么这不被视为对象),但我不确定。
  2. 有没有办法使用Scala的Int类型?
  3. 来实现这一目标
  4. 将scala和java类型混合起来是否可以接受?这是一个好习惯吗?

2 个答案:

答案 0 :(得分:1)

第一个问题是你在错误的对象上调用方法:obj没有handleInt方法,MyObject。第二种是边缘情况:invoke需要Object... varargs而Scala不会自动将Int直接转换为Object,因为这不是您通常想做的事情。您可以使用类型归档说“将此Int加入Integer”,然后Scala会自动将其翻译为Object

所以,结合以下两个修正:您无需更改handleIntval method,只需

val rsp = method.invoke(MyObject, 3: Integer)

要回答您的最后一个问题:使用Integerjava.lang.Double等在Scala代码中不常见,但这并不是特别有问题。反射是您可能必须使用它们的区域之一。

答案 1 :(得分:0)

不,我们不能使用Scala类型。

可以混合使用Java和Scala类型。

由于反射处理在运行时读取类字节码。在字节码级别,只有可见的类型是Java类型,因为所有scala类型都归结为Java类型。