2017-09-21 4 views
2

Ich weiß Inline Schlüsselwort bedeutet, um den Anruf Overhead zu vermeiden Aufruf einer Funktion. Aber ich kann nicht herausfinden, wofür eine Erweiterungseigenschaft inline ist.Kotlin Inlined Extension Eigenschaft

Let sagen wir zwei Erweiterungseigenschaft foo genannt haben und zum anderen mit inlined Bar gestattet

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

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

einer von ihnen durchführen, Gent wir die erwartete Ausgabe, die aktuelle Uhrzeit.

Der Bytecode für diese Datei ist dies unter:

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 
} 

Wir können beide sehen ähnlich, aber differents nur auf diesen Linien:

foo Extrakt:

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

Bar Extrakt:

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

Ich verstehe wirklich nicht, was hier passiert. Kann mir jemand zeigen, was ist das Verhalten, oder das Äquivalent in Java, oder etwas dafür?

bearbeiten

Da der Compiler den Inhalt inlined Eigenschaft ersetzen, kann es praktisch jede Erweiterungseigenschaft Inline keine schweren Operationen zu haben?

Danke

Antwort

1

Von Kotlin's doc,

anzumerken, dass, da Erweiterungen eigentlich keine Mitglieder in Klassen einsetzen, gibt es keine effiziente Möglichkeit für eine Erweiterung Eigenschaft ein backing field zu haben.

und also,

Der inline Modifikator kann auf Accessoren von Eigenschaften verwendet werden, die keine dahinter liegende Feld haben.

Wie oben erwähnt, eine Inline-Erweiterungseigenschaft keine dahinter liegende Feld hat. Sie können eine Erweiterung Eigenschaft als ein Paar von statischen Getter/Setter, so behandeln:

//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-Eigenschaft bedeutet, dass der Code der Getter/Setter-Funktion wird in den Aufrufort inlined werden, wenn die Eigenschaft Zugriff (wie reguläre Inline-Funktionen).

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

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

Für den Bytecode, die Sie in der Frage abgeben, sorry, dass ich nicht in der Lage sind zu erklären, was passiert ist. Aber Sie können versuchen, einen Blick auf den Bytecode des folgenden Codes zu nehmen:

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

, wo "".foo die Getter-Funktion aufrufen, aber "".bar nicht.

+0

Danke für die Antwort, ich denke, der Bytecode ist nur mehr als Sie vorschlagen. Was macht es gut, jede Erweiterungseigenschaft zu inline zu schreiben? – crgarridos

+0

@crgarridos Meistens ist der Overhead von Funktionsaufrufen keine große Sache. Ich würde 'inline' verwenden, wenn ich reparierte Typparameter brauche. Sie können sich diese [Frage] (https://stackoverflow.com/questions/43292802/what-are-the-use-cases-of-kotlin-inline-properties) als Referenz ansehen. – BakaWaii

+1

Ich habe eine Verwendung gefunden: 'Inline-Wert T.TAG: String get() = T :: class.java.simpleName' :) – crgarridos

Verwandte Themen