我知道 inline 关键字的意思是避免调用函数时产生开销。但我不确定将一个扩展属性标记为 inline 会起什么作用?
假设我们有两个扩展属性,分别命名为 foo 和另一个标记为 inline 的属性 bar
val Any.foo : Long
get() = Date().time
inline val Any.bar : Long
get() = Date().time
执行它们中的任何一个,我们都可以得到预期的输出,即当前时间。这个文件的字节码如下:
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 提取: 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中的相当之处,或对此有什么用处吗?
编辑
考虑到编译器将替换内联属性的内容,是否将每个扩展属性内联化并且没有繁重操作会更方便呢?
谢谢
inline
。你可以参考这个问题。 - BakaWaiiinline val <reified T> T.TAG : String get() = T::class.java.simpleName
:) - crgarridosT::class.qualifiedName
,如此处所建议,因为存在这个问题。 - BakaWaii