私は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
)。囲むクラス。
しかし、この場合、Scalaが内部的に1つを追加しない限り、包含するクラスはVec2
ではありません(ただし、java.lang.Class.getEnclosingClass()
が私のためにnull
を返します)。
私の質問は、反射を使用してScalaクラスをインスタンス化する方法です。 Scalaのコンストラクタが暗黙的に期待する追加のパラメータはありますか?
'newInstance'は' java.lang.Object'サブタイプの引数を除いているので、 'ctor.newInstance(params.map(_。asInstanceOf [Object]):_ *)'のように ' Float' –
ありがとう、それが助けになった! また、Vasilに感謝します。私は、配列[AnyRef]を作成する私が作業しているジェネリッククラスでこの問題にぶつからなかった。私が投稿した例は単純化されたバージョンでした。 :) – pdinklag
@Vasil Javaの場合と同様に、Scalaは基本的なプリミティブ型を持つものを自動化するので、Scalaの 'Float'は' float'または 'java.lang.Float'です。スカラのvarargsは 'Seq'を使い、Seqは消去された型なので、あなたが渡しているものは既にボックス化されており、' Object'のサブクラス化されていることが確かである。 –