带Int参数的Scala反射



在下面的代码中,我试图调用一个对象的方法,它有一个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)隐式转换的结果类型必须是more比AnyRef

具体
    val rsp    = method.invoke(obj, 3)

Error:(106,41) type mismatch;find: 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)
}

我的问题是:

    有人能解释一下为什么会这样吗?我认为 scala的Int封装了java的原始int(这就是为什么它不被认为是对象),但我不确定。
  1. 有一种方法来实现这使用Scala的Int类型?
  2. 像这样混合scala和java类型是可以接受的吗?这是一个好的实践吗?

第一个问题是您在错误的对象上调用方法:obj没有handleInt方法,MyObject有。第二种是一种边缘情况:invoke接受Object...变量,Scala不会自动将Int直接转换为Object,因为这不是你通常想要做的。你可以使用类型归属来表示"box this Int into an Integer ",然后Scala会自动将其上转换为Object

所以,结合这两个修复:你不需要改变handleIntval method,只需
val rsp = method.invoke(MyObject, 3: Integer)

回答你的最后一个问题:使用Integer, java.lang.Double等不应该在Scala代码中常见,但它不是特别有问题。反射就是其中一个需要用到它们的地方

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

可以混合Java和Scala类型

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

相关内容

  • 没有找到相关文章