Kotlin内联扩展属性

我知道内联关键字的意思是避免调用开销调用一个函数。 但我不明白什么内联扩展属性工作?

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

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

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

这个文件的字节码如下:

 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. ()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. ()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提取物:

  LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0 MAXSTACK = 2 MAXLOCALS = 1 

酒吧提取物:

  LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0 LOCALVARIABLE $i$f$getBar I L0 L2 1 MAXSTACK = 2 MAXLOCALS = 2 

我真的不明白这里发生了什么事。 有人可以指点我看看是什么行为,或在Java中的等价物,或者一些使用这个?

编辑

由于编译器会替换内联属性的内容,可能会方便内联每个不具有繁重操作的扩展属性?

谢谢

从Kotlin的文档中 ,

请注意,由于扩展实际上并没有将成员插入到类中,所以扩展属性没有有效的方法来拥有后台字段

而且,

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` } 

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

 //In Kotlin val x = "".foo val y = "".bar //Generated code val x = InlinedExtensionPropertyKt.getFoo("") val y = Date().time 

对于您在问题中发布的字节码,抱歉,我无法解释发生了什么。 但是你可以试着看下面代码的字节码:

 fun get() { val x = "".foo val y = "".bar } 

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