Why can't I set a UShort using reflection in kotlin? I extracted my problem into a unit test.
My test looks like this:
class Junk {
var DA: UShort? = null
}
class Tests {
@Test
fun testSetShort() {
var uut = Junk()
val value = 100
val expect = 100
val properties: Collection<KProperty<*>> = Junk::class.memberProperties
val property = properties.find { property -> property.name == "DA" }
if (property is KMutableProperty<*>) {
property.setter.call(uut, value.toUShort()) /* FAILS HERE */
}
assertEquals(expect, uut.DA)
System.err.println("ok")
}
}
The result is
argument type mismatch
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:498)
at kotlin.reflect.jvm.internal.calls.CallerImpl$Method.callMethod(CallerImpl.kt:97)
at kotlin.reflect.jvm.internal.calls.CallerImpl$Method$Instance.call(CallerImpl.kt:113)
at kotlin.reflect.jvm.internal.calls.InlineClassAwareCaller.call(InlineClassAwareCaller.kt:142)
at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:108)
at Tests.testSetShort(testSetUshort.kt:24)
Things I have tried:
- Force value to be of type UShort? in case the nullability was the problem (though that's not a problem when I try to do the same thing to a nullable String var)
it's a problem with inline classes. as you know inline classed are still experimental and
UShort
is an inline class which acts as a wrapper aroundShort
:let's take a look at the bytecode for your code. this is the summarized bytecode of your
DA
property:as you know inline classes should be ignored and deleted after compilation but because you defined
DA
as nullable, the compiled type is stillUShort
instead ofShort
.however, when you call
Int.toUShort
on an object, the compiled code has no sign ofUShort
and it converts toShort
instead(as it should because it's an inline class). that's why you get anargument type mismatch
error. because the setter needs aUShort
but you are giving it aShort
.that explains why your code runs successfully with
Short
instead ofUShort
.anyways, if you really need to use
UShort
in your code, you should not make it nullable, use alateinit var
instead and it works fine. because if it's not nullable, theDA
property's type would beShort
after compilation