2015-12-02 90 views
0

我有一个工具试图构建各种scala集合的子类的实例,例如scala.collection.Seq。我不知道应该建立什么特定的类,所以我尝试使用反射来获取伴随对象中的apply方法,如下所示(类似于声明List[Int](1, 2, 3))。通过scala反射的应用方法实例化scala集合

import scala.reflect.runtime.{universe => ru} 
import scala.reflect.runtime.universe._ 

def makeNewInstance[T <: scala.collection.Seq[_]](clazz: Class[T], args: List[_]): T = { 
    val clazzMirror: ru.Mirror = ru.runtimeMirror(clazz.getClassLoader) 
    val clazzSymbol = clazzMirror.classSymbol(clazz) 
    val companionObject = clazzSymbol.companion.asModule 
    val instanceMirror = clazzMirror reflect (clazzMirror reflectModule companionObject).instance 
    val typeSignature = instanceMirror.symbol.typeSignature 
    val name = "apply" 
    val ctor = typeSignature.member(TermName(name)).asMethod 
    instanceMirror.reflectMethod(ctor)(args:_*).asInstanceOf[T] 
} 
makeNewInstance(clazz = classOf[scala.collection.mutable.ListBuffer[Int]], args = List[Int](1,2,3))                         

尽管如此,我得到以下例外。我无法弄清楚我应该传递给apply方法。

java.lang.IllegalArgumentException: argument type mismatch 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaVanillaMethodMirror1.jinvokeraw(JavaMirrors.scala:373) 
at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaMethodMirror.jinvoke(JavaMirrors.scala:339) 
at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaVanillaMethodMirror.apply(JavaMirrors.scala:355) 
at Main$$anon$1.makeNewInstance(test.scala:12) 
at Main$$anon$1.<init>(test.scala:15) 
at Main$.main(test.scala:1) 
at Main.main(test.scala) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:70) 
at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31) 
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:101) 
at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:70) 
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101) 
at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22) 
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39) 
at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29) 
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39) 
at scala.tools.nsc.ScriptRunner.scala$tools$nsc$ScriptRunner$$runCompiled(ScriptRunner.scala:175) 
at scala.tools.nsc.ScriptRunner$$anonfun$runScript$1.apply(ScriptRunner.scala:192) 
at scala.tools.nsc.ScriptRunner$$anonfun$runScript$1.apply(ScriptRunner.scala:192) 
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1$$anonfun$apply$mcZ$sp$1.apply(ScriptRunner.scala:161) 
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply$mcZ$sp(ScriptRunner.scala:161) 
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:129) 
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:129) 
at scala.tools.nsc.util.package$.trackingThreads(package.scala:43) 
at scala.tools.nsc.util.package$.waitingForThreads(package.scala:27) 
at scala.tools.nsc.ScriptRunner.withCompiledScript(ScriptRunner.scala:128) 
at scala.tools.nsc.ScriptRunner.runScript(ScriptRunner.scala:192) 
at scala.tools.nsc.ScriptRunner.runScriptAndCatch(ScriptRunner.scala:205) 
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:67) 
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87) 
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98) 
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103) 
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) 

感谢您提前提供任何帮助。

回答

0

我会回答我的问题,检查构造函数接受可变参数与否:

if (ctor.isVarargs) instanceMirror.reflectMethod(ctor)(args.toList).asInstanceOf[T] else instanceMirror.reflectMethod(ctor)(args:_*).asInstanceOf[T]

感谢谁指出我在正确的方向上的朋友。