2017-03-22 2 views
0

Hallo, wenn ich Kotlin zum Programmieren von Android habe ich lateinit im Code gesehen. Was ist das Äquivalent in Java? Wie kann ich diesen Code von Kotlin nach Java ändern? Kotlin Lateinit Korrespondent Java

public class MyTest { 
    lateinit var subject: TestSubject 
} 
+0

Verwenden Sie einfach java 'getter', in dem Sie überprüfen, ob es initialisiert ist, wenn nicht ein –

Antwort

2

lateinit in Kotlin gibt es so, dass Sie nicht nullable Typen für Variablen haben können, die Sie nicht initialisieren können, sobald die Klasse, die sie enthält, erstellt wird.

Wenn Sie in Ihrem Beispiel lateinit nicht verwenden, müssen Sie die subject Nullable machen, da sie mit einem Wert initialisiert werden muss.

public class MyTest { 
    var subject: TestSubject? = null 
} 

Dies würde Sie zwingen, jedes Mal, wenn es null Kontrollen zu tun verwenden, was hässlich ist, so dass Sie es als lateinit stattdessen markieren können.


In Java, Sie haben dieses Problem nicht wirklich, da alles NULL-Werte zulässt, und ein nicht initialisierte Feld zu erklären ist nichts Besonderes:

public class JavaTest { 
    TestSubject subject; 
} 

Diese initialisiert subject zu null, so ist es praktisch gleichwertig zu dem nicht-lateinit Kotlin-Beispiel.

Der einzige wirkliche Unterschied zwischen der lateinit Version in Kotlin und der Java-Version ist, dass Sie eine spezifischere Ausnahme erhalten, wenn eine nicht initialisierte Eigenschaft in Kotlin zuzugreifen versuchen, nämlich ein UninitializedPropertyAccessException, die es einfacher debuggen machen als zu haben, Suchen Sie nach der Ursache für ein generisches NullPointerException.


Wenn Sie wirklich dieses leicht unterschiedliches Verhalten wollen, könnten Sie Ihre Java-Objekte in einer Art Wrapper wickeln, aber ich glaube nicht, dass der syntaktische Aufwand lohnen würde, dies zu tun.Ein sehr einfacher (nicht Thread-sicher, zum Beispiel) Weg, dies zu tun wäre:

Haben Sie eine generische Wrapper-Klasse für Eigenschaften:

public class Property<T> { 

    private T value = null; 

    public T get() { 
     if (value == null) 
      throw new UninitializedPropertyAccessException("Property has not been initialized"); 
     return value; 
    } 

    public void set(T value) { 
     if (value == null) 
      throw new IllegalArgumentException("Value can't be null"); 
     this.value = value; 
    } 

} 

Verwenden Sie diesen Wrapper in Ihren Klassen:

public class JavaTest { 
    Property<TestSubject> subject = new Property<>(); 
} 

Und dann würde dieser Gebrauch Sie die nicht initialisierten Ausnahme geben:

JavaTest test = new JavaTest(); 
test.subject.get(); 

Und dieser würde ru n fein:

JavaTest test = new JavaTest(); 
test.subject.set(new TestSubject()); 
test.subject.get(); 

Edit: dies sehr ähnlich ist, wie lateinit Werke in Kotlin, wenn Sie den Bytecode von Ihrem Beispiel Java dekompilieren, das ist, was man bekommt:

public final class MyTest { 
    @NotNull 
    public TestSubject subject; 

    @NotNull 
    public final TestSubject getSubject() { 
     TestSubject var10000 = this.subject; 
     if(this.subject == null) { 
     Intrinsics.throwUninitializedPropertyAccessException("subject"); 
     } 
     return var10000; 
    } 

    public final void setSubject(@NotNull TestSubject var1) { 
     Intrinsics.checkParameterIsNotNull(var1, "<set-?>"); 
     this.subject = var1; 
    } 
} 

Im Grunde legt der Compiler den Code für die Überprüfung des Eigenschaftszugriffs innerhalb der Klasse selbst (+ verwendet einige Hilfsmethoden) anstatt einen Wrapper zu verwenden, was effizienter ist.

0

Es gibt keine solche Eigenschaft in Java, die die Initialisierung der Eigenschaft verzögert. Aber ich denke, das Verhalten in Kotlin und Java ist ziemlich ähnlich.

Hier sind meine zwei Cent:

In Kotlin eine lateinit Eigenschaft Zugriff, bevor es wirft eine spezielle Ausnahme initialisiert wurde, die eindeutig die Eigenschaft identifiziert, auf die zugegriffen und die Tatsache, dass es nicht initialisiert wurde. (Referenz: https://kotlinlang.org/docs/reference/properties.html).

In Java wird auch NullPointerException (NPE) ausgelöst, die darauf hinweist, dass die Eigenschaft, auf die zugegriffen wird, Null ist.

Der einzige Unterschied könnte sein, dass NPE eine Laufzeitausnahme ist.

+0

erstellen' UninitializedPropertyAccessException' ist auch eine Laufzeitausnahme. – zsmb13

Verwandte Themen