首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Kotlin内联扩展属性

Kotlin内联扩展属性
EN

Stack Overflow用户
提问于 2017-09-21 08:26:24
回答 1查看 3.8K关注 0票数 12

我知道内联关键字意味着避免调用开销调用函数。但是我不知道扩展属性是为了什么工作的?

假设有两个名为foo的扩展属性,另一个是内联的名为bar的扩展属性。

代码语言:javascript
运行
复制
val Any.foo : Long
    get() = Date().time

inline val Any.bar : Long
    get() = Date().time

执行它们中的任何一个,我们就能得到预期的输出,当前的时间。

此文件的字节码如下:

代码语言:javascript
运行
复制
public final class InlinedExtensionPropertyKt {

  public final static getFoo(Ljava/lang/Object;)J
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
   L0
    ALOAD 0
    LDC "$receiver"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
   L1
    LINENUMBER 9 L1
    NEW java/util/Date
    DUP
    INVOKESPECIAL java/util/Date.<init> ()V
    INVOKEVIRTUAL java/util/Date.getTime ()J
    LRETURN
   L2
    LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1

  public final static getBar(Ljava/lang/Object;)J
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
   L0
    ALOAD 0
    LDC "$receiver"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
   L1
    LINENUMBER 12 L1
    NEW java/util/Date
    DUP
    INVOKESPECIAL java/util/Date.<init> ()V
    INVOKEVIRTUAL java/util/Date.getTime ()J
    LRETURN
   L2
    LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
    LOCALVARIABLE $i$f$getBar I L0 L2 1
    MAXSTACK = 2
    MAXLOCALS = 2

  @Lkotlin/Metadata;(mv={1, 1, 7}, bv={1, 0, 2}, k=2, d1={"\u0000\u000e\n\u0000\n\u0002\u0010\u0009\n\u0002\u0010\u0000\n\u0002\u0008\u0005\"\u0016\u0010\u0000\u001a\u00020\u0001*\u00020\u00028\u00c6\u0002\u00a2\u0006\u0006\u001a\u0004\u0008\u0003\u0010\u0004\"\u0015\u0010\u0005\u001a\u00020\u0001*\u00020\u00028F\u00a2\u0006\u0006\u001a\u0004\u0008\u0006\u0010\u0004\u00a8\u0006\u0007"}, d2={"bar", "", "", "getBar", "(Ljava/lang/Object;)J", "foo", "getFoo", "test sources for module app"})
  // compiled from: InlinedExtensionPropertyKt.kt
}

我们可以看到,这两者是相似的,但只有在这两行不同:

foo提取液:

代码语言:javascript
运行
复制
    LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1

bar提取:

代码语言:javascript
运行
复制
    LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
    LOCALVARIABLE $i$f$getBar I L0 L2 1
    MAXSTACK = 2
    MAXLOCALS = 2

我真的不明白这里发生了什么事。有人能指给我看一下java中的行为,或者等价的东西,或者它的一些用途吗?

编辑

如果编译器将替换内联属性的内容,那么是否可以方便地内联不需要大量操作的每个扩展属性?

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-21 09:30:45

来自科特林氏病

注意,由于扩展实际上并不将成员插入类中,所以扩展属性没有有效的方法来拥有支持场

也是

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

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

代码语言:javascript
运行
复制
//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`
}

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

代码语言:javascript
运行
复制
//In Kotlin
val x = "".foo
val y = "".bar

//Generated code
val x = InlinedExtensionPropertyKt.getFoo("")
val y = Date().time

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

代码语言:javascript
运行
复制
fun get() {
    val x = "".foo
    val y = "".bar
}

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

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46338963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档