0
votes

In the below code, I try to invoke an object's method that has an Int parameter (giving it a value of 3). This returns an error that Int and 3 are incompatible types.

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

Error:(106, 41) the result type of an implicit conversion must be more specific than AnyRef

    val rsp    = method.invoke(obj, 3)

Error:(106, 41) type mismatch; found : Int(3) required: Object

    val rsp    = method.invoke(obj, 3)

I tried modifying a lot of things here, the only way this could work is by changing all signatures to Java's Integer. The code will look like this:

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

My question(s) are:

  1. Can someone explain why this happens? I think scala's Int wraps java's primitive int (which is why this is not considered an object), but I'm not sure.
  2. Is there a way to achieve this using Scala's Int type?
  3. Is it acceptable to mix scala and java types like this? Is it a good practice?
2

2 Answers

1
votes

The first problem is that you invoke method on the wrong object: obj doesn't have handleInt method, MyObject does. The second is kind of an edge case: invoke takes Object... varargs and Scala doesn't automatically convert an Int directly to Object because that's not what you normally want to do. You can use a type ascription to say "box this Int into an Integer" and then Scala will upcast it to Object automatically.

So, combining these 2 fixes: you don't need to change handleInt or val method, just

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

To answer your final question: use of Integer, java.lang.Double, etc. shouldn't be common in Scala code, but it isn't particularly problematic. And reflection is one of the areas where you may have to use them.

0
votes

No we cannot use Scala types.

Its Ok to mix Java and Scala types.

As reflection deals with reading class bytecode at Runtime. At bytecode level only types that are visible are the Java types because all scala types are boiled down to Java types.