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?
newInstance
excepts arguments ofjava.lang.Object
subtype, so you will rather have to do something likector.newInstance(params.map(_.asInstanceOf[Object]): _*)
forFloat
– Roxane