The init
block of the value class
can contain processing.
@JvmInline
value class Value(val value: Int) {
init {
if (100 < value) throw IllegalArgumentException()
}
}
This will be compiled into a method named constructor-impl
in the bytecode.
When instantiating a value class
using Java reflection, both constructor-impl
and box-impl
must be called in order to be equivalent to instantiating it on Kotlin
.
On the other hand, there is no evidence that constructor-impl
is called in the spring-framework
, and only box-impl
seems to be called.
Is this an intentional design?
Comment From: sdeleuze
I have reached Kotlin team to get related guidance.
Comment From: efemoney
Coroutine handling (in CoroutineUtils.invokeSuspendingFunction
) calls box-impl
directly. Ideally that would call the value class single primary constructor gotten from kotlin reflection.
Comment From: sdeleuze
@efemoney Unless I am mistaken, and as confirmed by the Kotlin team, this is not possible due to #31698.
Comment From: efemoney
Yeah I saw that but its slightly different from what I am saying which is
value class PlanId(val value: Int) {
init {
require(value >= 0) // Throw if value is negative
}
}
assertEquals(
PlanId(21),
PlanId::class.primaryConstructor!!.call(21),
)
assertFails {
PlanId::class.primaryConstructor!!.call(-21)
}
The only issue is this will need to use kotlin reflection KClasses.getPrimaryConstructor(kClass).call(args[index])
, I dont know if thats desired or not
Comment From: sdeleuze
Good point, should be ok to use this.