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
UShortis 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
DAproperty:as you know inline classes should be ignored and deleted after compilation but because you defined
DAas nullable, the compiled type is stillUShortinstead ofShort.however, when you call
Int.toUShorton an object, the compiled code has no sign ofUShortand it converts toShortinstead(as it should because it's an inline class). that's why you get anargument type mismatcherror. because the setter needs aUShortbut you are giving it aShort.that explains why your code runs successfully with
Shortinstead ofUShort.anyways, if you really need to use
UShortin your code, you should not make it nullable, use alateinit varinstead and it works fine. because if it's not nullable, theDAproperty's type would beShortafter compilation