gpt4 book ai didi

android - Kotlin 默认构造函数中的两种附加类型?

转载 作者:太空宇宙 更新时间:2023-11-03 13:07:58 24 4
gpt4 key购买 nike

因为我一直在使用 kotlin-reflect 来调用我的默认值并声明一个,所以我看到了第二个不同的构造函数。

我意识到我的构造函数中添加了两个不同的字段 int arg3kotlin.jvm.internal.DefaultConstructorMarker arg4

data class Model(
@SerializedName("xyz") val entity: String?,
@SerializedName("abc") val id: Long? = null
)
val constructors = clazz.declaredConstructors // how I call the constructors

我真正的问题是为什么我有这两个字段,它背后的逻辑是什么?

提前致谢。

最佳答案

这两个参数被添加到 Kotlin 编译器为所有具有默认参数的函数和构造函数生成的特殊合成成员中。

通过Java反射,你可以通过检查isSynthetic()过滤掉这些合成函数和构造函数并找到不是的那个。

整数参数是位掩码。当从 Kotlin 调用这样的函数时,会生成一个位掩码并将其作为参数传递。这些位显示函数的哪些默认参数被显式传递,哪些应使用默认值。

DefaultConstructorMarker 参数用于确保合成构造函数(接受位掩码)与具有相同参数签名和 Int 最后。传递给标记参数的参数不以任何方式使用,它始终为 null

事实上,每个函数或构造函数分别生成了两个方法或构造函数,它们至少有一个默认参数:一个与声明的签名相同,没有额外的参数,另一个也接受位掩码和标记。

如果你检查这样一个函数的字节码,你会发现函数声明大致如下:

fun foo(bar: String, baz: List<String> = emptyList(), qux: Set<String> = emptySet()) = 0

字节码中真正的方法是:

// access flags 0x19
// signature (Ljava/lang/String;Ljava/util/List<Ljava/lang/String;>;Ljava/util/Set<Ljava/lang/String;>;)I
// declaration: int foo(java.lang.String, java.util.List<java.lang.String>, java.util.Set<java.lang.String>)
public final static foo(
Ljava/lang/String;
Ljava/util/List;
Ljava/util/Set;
)I
// annotable parameter count: 3 (visible)
// annotable parameter count: 3 (invisible)
@Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
@Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 1
@Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 2
L0
ALOAD 0
LDC "bar"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
ALOAD 1
LDC "baz"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
ALOAD 2
LDC "qux"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
L1
LINENUMBER 16 L1
ICONST_0
IRETURN
L2
LOCALVARIABLE bar Ljava/lang/String; L0 L2 0
LOCALVARIABLE baz Ljava/util/List; L0 L2 1
LOCALVARIABLE qux Ljava/util/Set; L0 L2 2
MAXSTACK = 2
MAXLOCALS = 3

生成的处理位掩码并在必要时计算默认值的包装器是一个单独的方法:

// access flags 0x1009
public static synthetic foo$default(
Ljava/lang/String;
Ljava/util/List;
Ljava/util/Set;
I
Ljava/lang/Object;
)I
ILOAD 3
ICONST_2
IAND
IFEQ L0
L1
LINENUMBER 16 L1
INVOKESTATIC kotlin/collections/CollectionsKt.emptyList ()Ljava/util/List;
ASTORE 1
L0
ILOAD 3
ICONST_4
IAND
IFEQ L2
INVOKESTATIC kotlin/collections/SetsKt.emptySet ()Ljava/util/Set;
ASTORE 2
L2
ALOAD 0
ALOAD 1
ALOAD 2
INVOKESTATIC FooKt.foo (Ljava/lang/String;Ljava/util/List;Ljava/util/Set;)I
IRETURN
MAXSTACK = 3
MAXLOCALS = 5

注意后者如何检查位掩码(使用ILOAD 3ICONST_xIAND)然后有条件地(当IFEQ Lx 不会跳过它)计算默认参数。

构造函数与普通函数不同,其名称中不能有后缀$default,因此需要标记以避免可能的签名冲突。

关于android - Kotlin 默认构造函数中的两种附加类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53912047/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com