Estoy intentando invocar el método newInstance
de un constructor de una clase Scala (clase de caso o clase habitual, ambos se ven afectados).Número incorrecto de argumentos que invocan un constructor de Scala utilizando el reflejo
Sin embargo, estoy corriendo en un IllegalArgumentException
con la sugerencia número incorrecto de argumentos.
considerar lo siguiente:
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
}
}
La salida es la siguiente:
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)
he experimentado algo como esto en Java una vez. En ese caso, la clase que intentaba crear una instancia era una clase interna de otra clase, por lo que Java esperaba un parámetro adicional implícito, que era el objeto Class
de la clase adjunta (si la clase se declaró como estática) o una instancia de la clase adjunta
Sin embargo, en este caso no hay ninguna clase envolvente de Vec2
, a menos Scala agrega uno internamente (aunque, java.lang.Class.getEnclosingClass()
vuelve null
para mí).
Así que mi pregunta es cómo instanciar las clases de Scala utilizando la reflexión? ¿Hay algún parámetro adicional que los constructores de Scala esperan implícitamente?
'newInstance' excepto los argumentos del subtipo' java.lang.Object', por lo que tendrá que hacer algo como 'ctor.newInstance (params.map (_. AsInstanceOf [Object]): _ *)' for ' Float' –
¡Gracias, eso ayudó! También gracias Vasil. No me encontré con ese problema con la clase genérica en la que estoy trabajando, que crea una matriz [AnyRef]. El ejemplo que publiqué fue una versión simplificada. :) – pdinklag
@Vasil Al igual que con Java, Scala autoboxará cualquier cosa que tenga un tipo primitivo subyacente, por lo que un Scala 'Float' puede ser un' float' o un 'java.lang.Float'. Debido a que scala varargs usa 'Seq' y Seq es un tipo borrado, puede estar seguro de que lo que está pasando ya estará encasillado y subclasificará' Object' –