使用反射调用 Scala 构造函数的参数数量错误

发布于 2024-10-15 14:41:27 字数 2217 浏览 2 评论 0原文

我正在尝试调用 Scala 类(案例类或普通类,两者都会受到影响)的构造函数的 newInstance 方法。

但是,我遇到了 IllegalArgumentException,并提示参数数量错误

请考虑以下情况:

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

输出如下:

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)

我在 Java 中曾经经历过类似的事情。在这种情况下,我尝试实例化的类是另一个类的内部类,因此 Java 需要一个隐式附加参数,该参数可以是封闭类的 Class 对象(如果该类声明为static),或封闭类的实例。

但是,在这种情况下,不存在 Vec2 的封闭类,除非 Scala 在内部添加一个封闭类(尽管 java.lang.Class.getEnendingClass() 返回 null< /代码> 对我来说)。

所以我的问题是如何使用反射实例化 Scala 类? Scala 构造函数是否隐式期望任何其他参数?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

︶葆Ⅱㄣ 2024-10-22 14:41:27

newInstance 方法采用 varargs 参数。在 Scala 中(与 Java 不同),您不能只传递一个数组并自动将其视为所有参数。如果这就是您想要的,您需要像这样明确地执行此操作:

ctor.newInstance(params:_*)

您现在正在做的是将包含 2 个元素的数组作为第一个参数传递给构造函数。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文