为什么我不能在Kotlin中使用反射设置UShort?我将问题提取到单元测试中。
我的测试如下所示:
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")
}
}
结果是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)
我尝试过的事情:最佳答案
内联类存在问题。如您所知,内联类仍处于试验阶段,UShort
是内联类,用作Short
的包装器:
public inline class UShort @PublishedApi internal constructor(@PublishedApi internal val data: Short) : Comparable<UShort>
让我们看一下代码的字节码。这是DA
属性的摘要字节码:private Lkotlin/UShort; DA
@Lorg/jetbrains/annotations/Nullable;() // invisible
// access flags 0x11
public final getDA-XRpZGF0()Lkotlin/UShort;
@Lorg/jetbrains/annotations/Nullable;() // invisible
...
public final setDA-ffyZV3s(Lkotlin/UShort;)V
// annotable parameter count: 1 (visible)
// annotable parameter count: 1 (invisible)
@Lorg/jetbrains/annotations/Nullable;() // invisible, parameter 0
...
如您所知,内联类应在编译后被忽略并删除,但是由于您将DA
定义为可为空,因此编译后的类型仍然是UShort
而不是Short
。但是,当您在对象上调用
Int.toUShort
时,编译后的代码没有UShort
的迹象,而是改为转换为Short
(因为它是一个内联类,所以应该这样)。这就是为什么您会收到argument type mismatch
错误的原因。因为 setter 需要一个UShort
,但是您要给它一个Short
。这就解释了为什么您的代码使用
Short
而不是UShort
成功运行。无论如何,如果您确实需要在代码中使用
UShort
,则不应使其变为可为空,而应使用lateinit var
,它可以正常工作。因为如果不能为空,则编译后DA
属性的类型将为Short
var DA: UShort = 0u
//bytecode:
private S DA // S is JVM type for Short
// access flags 0x11
public final getDA-Mh2AYeg()S
...
// access flags 0x11
public final setDA-xj2QHRw(S)V
...
关于kotlin - 使用Kotlin-reflect设置可为空的UShort,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64394644/