Kotlin内联扩展属性

crg*_*dos 7 inline kotlin kotlin-extension jvm-bytecode

我知道内联关键字的意思是避免调用功能的调用开销。但是我不知道扩展属性可以用于什么内联?

假设我们有两个名为foo的扩展属性,另一个带有名为bar的内联属性

val Any.foo : Long
    get() = Date().time

inline val Any.bar : Long
    get() = Date().time
Run Code Online (Sandbox Code Playgroud)

执行其中的任何一个,我们将期望的输出,即当前时间。

该文件的字节码如下:

val Any.foo : Long
    get() = Date().time

inline val Any.bar : Long
    get() = Date().time
Run Code Online (Sandbox Code Playgroud)

我们可以看到两者相似,但仅在以下几行不同:

foo提取:

    LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1
Run Code Online (Sandbox Code Playgroud)

酒吧摘录:

    LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
    LOCALVARIABLE $i$f$getBar I L0 L2 1
    MAXSTACK = 2
    MAXLOCALS = 2
Run Code Online (Sandbox Code Playgroud)

我真的不明白这里发生了什么。有人可以指点我看一下它的行为,或java中的等效行为,或对此的一些用法吗?

编辑

给定编译器将替换内联属性的内容,可以方便地内联每个没有繁重操作的扩展属性。

谢谢

Bak*_*aii 5

根据Kotlin的文档

请注意,由于扩展实际上并未将成员插入类,因此扩展属性没有有效的方法来拥有backing field

inline修饰符可以用于没有后备字段的属性的访问器。

如上所述,内联扩展属性没有后备字段。您可以将扩展属性视为一对静态的getter / setter,如下所示:

//In Kotlin
var Any.foo : Long
    get() = Date().time
    set(value) {
        //Cannot access field here since extension property cannot have backing field
        //Do something with `obj`
    }

//In Java
public static long getFoo(Object obj) {
    return new Date().getTime();
}
public static void setFoo(Object obj) {
    //Do something with `obj`
}
Run Code Online (Sandbox Code Playgroud)

因此,内联属性意味着访问该属性时,getter / setter函数的代码将内联到调用站点中(与常规内联函数相同)。

//In Kotlin
val x = "".foo
val y = "".bar

//Generated code
val x = InlinedExtensionPropertyKt.getFoo("")
val y = Date().time
Run Code Online (Sandbox Code Playgroud)

对于您在问题中发布的字节码,对不起我无法解释正在发生的事情。但是您可以尝试查看以下代码的字节码:

fun get() {
    val x = "".foo
    val y = "".bar
}
Run Code Online (Sandbox Code Playgroud)

,其中"".foo将调用getter函数,但"".bar不会。

  • 我发现了一种用法:`inline val <reified T> T.TAG:String get()= T :: class.java.simpleName` :) (2认同)
  • 是的,这是对具体化类型参数的有效且良好的使用。为了使它更好,我将按照[此处]的建议使用`T::class.qualifiedName`(/sf/ask/3208874721/ tag-constant-in-kotlin)因为这个[问题](https://medium.com/@elye.project/the-danger-of-using-class-getsimplename-as-tag-for-fragment-5cdf3a35bfe2) 。 (2认同)