- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
2.8.0.h: constructor, default parameter value and reflection
Tue, 2010-03-30, 02:54
I'd like to create an instance using reflection. The
class has a single constructor which takes a parameter
which has a default value. How do I get to the correct
constructor in Scala?
Below is a test class which has one class with with two
constructors - and this one reflection works on. And
a second class which has a single constructor which
has a default value - and this one I can figure out how
to get a handle on so I can create an instance.
File Test.scala
import java.lang.reflect.Constructor
object Util {
val EMPTY_CLASS_ARRAY = Array[Class[_]]()
val EMPTY_OBJECT_ARRAY = Array[Any]()
}
class Builder[T](interfaceClass: Class[T]) {
def lookupClass(name: String) : Class[_ <: T] = {
var clz = Class.forName(name)
clz.asSubclass(interfaceClass)
}
def getConstructor(clz: Class[_ <: T],
parameterTypes: Array[Class[_]]): Constructor[_ <:
T] = {
clz.getConstructor(parameterTypes: _*)
}
def newInstance(constructor: Constructor[_ <: T],
parameterValues: Array[Any]): T = {
constructor.newInstance(parameterValues.map(_.asInstanceOf[AnyRef])
: _*)
}
}
class Works(name: String) {
def this() = this("Works")
def getName: String = name
}
class DoesNotWork(name: String = "DoesNotWork") {
def getName: String = name
}
import Util._
object Main {
def doWorks {
val builder = new Builder[Works](classOf[Works])
var clz: Class[_ <: Works] = builder.lookupClass("Works")
var constructor = builder.getConstructor(clz, EMPTY_CLASS_ARRAY)
var works: Works = builder.newInstance(constructor, EMPTY_OBJECT_ARRAY)
println("name="+works.getName)
}
def doesNotWork {
val builder = new Builder[DoesNotWork](classOf[DoesNotWork])
var clz: Class[_ <: DoesNotWork] = builder.lookupClass("DoesNotWork")
var constructor = builder.getConstructor(clz, EMPTY_CLASS_ARRAY)
var notworks: DoesNotWork = builder.newInstance(constructor,
EMPTY_OBJECT_ARRAY)
println("name="+notworks.getName)
}
def usage {
println("Enter either: \"works\" or \"doesnotworks\"")
}
def main(args: Array[String]) {
args match {
case Array("works") => doWorks
case Array("doesnotwork") => doesNotWork
case _ => usage
}
}
}
> scalac Test.scala
> scala Main
Enter either: "works" or "doesnotwork"
> scala Main works
name=Works
> scala Main doesnotwork
java.lang.NoSuchMethodException: DoesNotWork.()
at java.lang.Class.getConstructor0(Class.java:2706)
at java.lang.Class.getConstructor(Class.java:1657)
at Builder.getConstructor(Works.scala:19)
at Main$.doesNotWork(Works.scala:51)
at Main$.main(Works.scala:61)
at Main.main(Works.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
scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:55)
at
scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:22)
at
scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:61)
at
scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:55)
at
scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:61)
at
scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:153)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
Using reflection how can I tell if a class has constructors that
have default parameters and how can I call the one that will
build an instance using the default value.
Thanks
Richard
this class has no parameterless constructor in bytecode. if you want
to use the default argument you have to call the method
DoesNotWork$.MODULE$.init$default$1
to get the value "DoesNotWork" back, and then feed this into the
1-argument constructor.
more documentation on how defaults work is here: http://www.scala-lang.org/sid/1
lukas
On Tue, Mar 30, 2010 at 03:53, richard emberson <richard.emberson@gmail.com> wrote: