Неверное количество аргументов, вызывающих конструктор Scala с использованием отражения - PullRequest
6 голосов
/ 02 февраля 2011

Я пытаюсь вызвать метод newInstance конструктора класса Scala (класс case или обычный класс, оба затронуты).

Однако я сталкиваюсь с 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 включающего класса (если класс был объявлен как статический), либоэкземпляр включающего класса.

Однако в этом случае не существует включающего класса Vec2, если только Scala не добавит его внутренне (хотя java.lang.Class.getEnclosingClass() возвращает null для меня).

Итак, мой вопрос: как создать классы Scala с помощью отражения?Существуют ли какие-либо дополнительные параметры, которые конструкторы Scala ожидают неявно?

1 Ответ

11 голосов
/ 02 февраля 2011

Метод newInstance принимает параметр varargs.В Scala (в отличие от Java) вы не можете просто передать массив и автоматически обработать его как все аргументы.Если это то, что вам нужно, вам нужно сделать это явно так:

ctor.newInstance(params:_*)

В данный момент вы делаете передачу массива с 2 элементами в качестве первого аргумента конструктору.

...