I'm trying to invoke the newInstance
method of a constructor of a Scala class (case class or usual class, both are affected).
However, I'm running into a IllegalArgumentException
with the hint wrong number of arguments.
Consider the following:
case class Vec2(x: Float, y: Float)
object TestApp {
def main(args: Array[String]) {
//after some research I found the last constructor always to be the default
val ctor = classOf[Vec2].getConstructors.last
println("ctor = " + ctor)
println("takes parameters: " + ctor.getParameterTypes.length)
val params = new Array[Float](2)
params.update(0, 1.0f)
params.update(1, -1.0f)
println("num parameters: " + params.length)
println("trying to create new instance...")
try {
val x = ctor.newInstance(params)
println("new instance: " + x)
}
catch {
case ex => ex.printStackTrace
}
}
The output is as follows:
ctor = public pd.test.Vec2(float,float)
takes parameters: 2
num parameters: 2
trying to create new instance...
java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at pd.test.TestApp$.main(TestApp.scala:60)
at pd.test.TestApp.main(TestApp.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
I have experienced something like this in Java once. In that case the class I was trying to instantiate was an inner class of another class, so Java expected an implicit additional parameter, which was either the Class
object of the enclosing class (if the class was declared as static), or an instance of the enclosing class.
However, in this case there is no enclosing class of Vec2
, unless Scala adds one internally (though, java.lang.Class.getEnclosingClass()
returns null
for me).
So my question is how to instantiate Scala classes using reflection? Are there any additional parameters Scala constructors expect implicitly?
The newInstance
method takes a varargs parameter. In Scala (unlike Java), you can't just pass an array and have it automatically treated as all the arguments. If that's what you want you need to do it explicitly like this:
ctor.newInstance(params:_*)
What you're doing at the moment is passing an array with 2 elements as the first argument to the constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With