Given a domain class with a parameterless constructor, how do we get a reference to that constructor through the Reflection API?
Consider for example a Student data class, such as:
data class Student(var nr: Int = 0, var name: String? = null)
Notice, we can confirm the presence of the parameterless constructor through javap that shows:
public pt.isel.Student(int, java.lang.String);
descriptor: (ILjava/lang/String;)V
public pt.isel.Student(int, java.lang.String, int, kotlin.jvm.internal.DefaultConstructorMarker);
descriptor: (ILjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public pt.isel.Student();
descriptor: ()V
Yet, none of the following approaches returns the parameterless constructor:
- Approach 1 -
primaryConstructor:
val constructor = Student::class.primaryConstructor
- Approach 2 - All constructors declared in the class:
// java.util.NoSuchElementException: Collection contains no element matching the predicate
val constructor = Student::class.constructors.first { it.parameters.isEmpty() }
Alternatively, we can proceed via Java Reflection that works fine, but it should not be necessary such detour:
val constructor = Student::class.java.getDeclaredConstructor()
Second, why do we need that? Because we want to instantiate a domain class at runtime. Yes, we know that createInstance() of KClass do that job. But it throws IllegalArgumentException: Class should have a single no-arg constructor if there is no parameterless constructor.
Thus, we would like to check before-hand if we could call the createInstance() with no exceptions.
javap, which is a Java thing. That's unrelated to the Kotlin reflection API.createInstance()is part of Kotlin Reflectionm API and it may claimIllegalArgumentException: Class should have a single no-arg constructor. All this in Kotlin! IMO, it should also provide a way in Kotlin to let me know if I can make a call tocreateInstance()without exceptions.createInstancedoesn't throw an exception forStudent? Have you read its documentation? It also checks if the parameters are optional, not just whether the class has a parameterless constructor.createInstance()works fine, or not, and if we have to choose a different way of instantiating dynamically.