1
votes

In my limited experience with Scala, there is a error in my code:

class TagCalculation {
    def test_string(arg1: String,arg2: String) = arg1 + " " + arg2
    def test_int(arg1: Int,arg2: Int) = arg1 + arg2
  }
val get_test = new TagCalculation
//test int, by the way it's Ok for String
val test_int_para = Array(1,2)
val argtypes2 = test_int_para.map(_.getClass)
val method2 = get_test.getClass.getMethod("test_int", argtypes2: _*)
method2.invoke(get_test,test_int_para: _*)

Outputs:

console>:29: error: type mismatch;
found : Array[Int]
required: Array[_ <: Object]
method2.invoke(get_test,test_int_para: _*)

Why did this error happened?

2
Probably this will help you clarify: scala-lang.org/old/node/128.html On a side note: your post doesn't look like a question.DeusEx
Arrays in Scala are invariant but in Java they are covariant. You'll need to cast it to Array[Object] (or declare it as that type)...insan-e
@DeusEx - I'm newer for using stackoverflow(It's very very good), so I may make some mistakes for its style. Oh, is there something to make my question well for a "question"? Thanks in advance:)meng
@insan-e - could you provided more details about your use case ?meng

2 Answers

3
votes

invoke()'s second parameter has type Array[_ <: Object]. That means, that type of passed array should extend Object. In Scala Object is synonym to AnyRef, and Int isn't AnyRef subtype, but is AnyVal subtype actually. Here is more detailed explanation: http://docs.scala-lang.org/tutorials/tour/unified-types.html

You passed Array[Int] as second parameter, that's why error happened. You need to pass Array[_ <: Object] instead.

So, what you really need is to pass Integer wrappers, which are AnyRefs, explicitly. You can transform all array Ints to Integers using Integer.valueOf method. Then, invoke() method just works:

scala> method2.invoke(get_test, test_int_para.map(Integer.valueOf): _*)
res2: Object = 3
0
votes

Instead of using Integer.valueOf (or Double, or Long, etc. etc.) there is a much simpler solution:

val test_int_para = Array[AnyRef](1,2)

Or if you already have val params: Array[Any], e.g. val params = Array(1,"string",df):

val paramsAsObjects = params.map(_.asInstanceOf[AnyRef])
someMethod.invoke(someObject, paramsAsObjects: _*)