I know inline keyword means to avoid the call overhead calling a funtion. But I can't figure out what inline a extension property work for?
Let say we have two extension property named foo and another with is inlined named bar
val Any.foo : Long
get() = Date().time
inline val Any.bar : Long
get() = Date().time
Executing any of them, we gent the expected output, the current time.
The bytecode for this file is this below:
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
}
We can see both are similar but differents only on these lines:
foo extract:
LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
MAXSTACK = 2
MAXLOCALS = 1
bar extract:
LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
LOCALVARIABLE $i$f$getBar I L0 L2 1
MAXSTACK = 2
MAXLOCALS = 2
I really don't understand what is happennig here. Can someone point me to see what is the behaviour, or the equivalent in java, or some use for this?
Edit
Given the compiler will replace the content of inlined property, it may convenient to inline every extension property having not heavy operations ?
Thank you
Extension functions are really-really helpful while writing code in Kotlin. You don't have to extend the class but you can add the functionality to even a final (non-open) class which will be resolved statically but how about extension properties.
Inline annotation means that the specific function, along with the function parameters, will be expanded at the call site; this helps reduce call overhead. Similarly, the inline keyword can be used with properties and property accessors that do not have the backing field. 1. Let’s try an example where we inline an accessor of property in Kotlin:
It does not actually modify the existing class, but it creates a callable function that can be called with a dot operation. In function extension, Kotlin allows to define a method outside of the main class. In the following example, we will see how the extension is implemented at the functional level.
Properties in Kotlin classes can be declared either as mutable, using the var keyword, or as read-only, using the val keyword. Copied! To use a property, simply refer to it by its name: Copied! The full syntax for declaring a property is as follows:
From Kotlin's doc,
Note that, since extensions do not actually insert members into classes, there's no efficient way for an extension property to have a backing field.
and also,
The
inline
modifier can be used on accessors of properties that don't have a backing field.
As mentioned above, an inline extension property does not have a backing field. You may treat an extension property as a pair of static getter/setter, like this:
//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`
}
So, inline property means that the code of the getter/setter function will be inlined into the call site when accessing the property (same as regular inline functions).
//In Kotlin
val x = "".foo
val y = "".bar
//Generated code
val x = InlinedExtensionPropertyKt.getFoo("")
val y = Date().time
For the bytecode that you post in the question, sorry that I am not able explain what is happening. But you may try to take a look at the bytecode of the following code:
fun get() {
val x = "".foo
val y = "".bar
}
, where "".foo
will invoke the getter function but "".bar
will not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With