为什么我不能在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类型吗?万一可为空是问题(虽然当我尝试对可为空的String var做同样的事情时这不是问题)
  • 最佳答案

    内联类存在问题。如您所知,内联类仍处于试验阶段,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/

    10-10 19:44