Skip to content
Anjunar/ DOCS

Constructors and parameters

Constructors create instances; methods and constructors share ResolvedParameter, which carries the parameter's name, its resolved type and its annotations.

Creating

findConstructor and newInstance

findConstructor finds a public constructor of the class by its parameter classes, findDeclaredConstructor any constructor, private ones included. newInstance passes the arguments in order.

scala
class User(val id: Long, val name: String) val constructor = TypeResolver.resolve(classOf[User]).findConstructor(classOf[Long], classOf[String]) val ada = constructor.newInstance(Long.box(1L), "Ada").asInstanceOf[User] println(ada.name) // Ada
Scala primitives are JVM primitives

classOf[Long] is the primitive long, which is what the constructor declares. Pass boxed values such as Long.box(1L) to newInstance.

Parameters

Names, types and annotations

Parameter names come from the class file. Scala 3 writes them by default; Java classes need javac -parameters, otherwise the names are arg0, arg1 and so on.

scala
val parameters = TypeResolver.resolve(classOf[User]) .findConstructor(classOf[Long], classOf[String]).parameters parameters.foreach(parameter => println(s"${parameter.name}: ${parameter.parameterType.name}"))
Output
id: long name: String

parameterType is resolved against the owning class, so a parameter of a generic base method reads as the concrete type in the subclass. For method parameters, annotations also include those of the same parameter in overridden methods.

No-argument construction

What frameworks usually need

Mappers create an empty instance and fill it through properties. That needs a public constructor without parameters.

scala
def create[T](clazz: Class[T]): T = val constructor = TypeResolver.resolve(clazz).findConstructor() require(constructor != null, s"${clazz.getName} needs a public no-argument constructor") constructor.newInstance().asInstanceOf[T]