Kotlins Typsystem ist ein Typ, der null sein kann.
Unterscheiden Sie zwischen Typen, die nicht sein können.
Fügen Sie für Typen, die null sein können, nach dem Typnamen ?
Hinzu.
val num: Int = null //Kompilierungsfehler kann nicht null sein
val num: Int? = null //OK, wenn nullbarer Typ
Sie können nicht direkt auf nulltolerante Funktionen und Eigenschaften zugreifen. Ein Kompilierungsfehler wird auftreten.
val num: Int? = null //Als nullbarer Typ deklariert
val floatNum = num.toFloat() //Kompilierungsfehler
Unzugänglich, wenn es null sein kann bedeutet Das Risiko einer NullPointerException ist stark reduziert.
In Java werden solche Nullprüfungen häufig angezeigt.
// Java
Dog dog = //Kann null sein
dog.run(); //Mögliche NullPointerException Ali
if (dog != null) {
dog.run(); //Null geprüft
}
Lassen Sie uns dasselbe mit Kotlin implementieren.
val dog: Dog? = //Kann null sein
dog.run() //Kompilierungsfehler
if (dog != null) {
dog.run() //OK für nullgeprüfte Blöcke
}
Funktionen für nulltolerante Objekte können nicht direkt aufgerufen werden. Automatisch in null umgewandelt nicht zulässiger Typ in null geprüft wenn Block Sie können die Funktion aufrufen. Dies wird als Smart Cast bezeichnet.
Kotlin hat auch eine bequemere Zuckerbeschichtungssyntax.
val dog: Dog? = //Kann null sein
dog?.run()
Sie können nach ? .
Auf Funktionsaufrufe und Eigenschaften zugreifen.
Wenn im obigen Beispiel "Hund" null ist, wird nur null zurückgegeben.
Dies wird als sicherer Anruf bezeichnet.
In Java wird ein solcher Downcast-Code angezeigt.
/*
*Die Hundeklasse ist eine Unterklasse der Tierklasse
*/
Animal animal = // ...
((Dog)animal).run(); //Möglichkeit der ClassCastException Ali
if (animal instanceof Dog) {
Dog dog = (Dog)animal;
dog.run();
}
Lassen Sie uns dasselbe mit Kotlin implementieren.
/*
*Die Hundeklasse ist eine Unterklasse der Tierklasse
*/
val animal: Animal = // ...
(animal as Dog).run() // //Möglichkeit der ClassCastException Ali
if (animal is Dog) {
animal.run()
}
Kotlin-Casts verwenden den Operator "as". Wenn die Umwandlung fehlschlägt, wird eine ClassCastException ausgelöst.
Das Java-Äquivalent "instanceof" ist der Operator "is". Dies ist auch von Smart Cast Im if-Block wird die Variable "animal" automatisch in den Hundetyp umgewandelt. Sie können die Methode der Hundeklasse so wie sie ist aufrufen.
Kotlin hat auch eine bequemere Zuckerbeschichtungssyntax.
val animal: Animal = // ...
(animal as? Dog)?.run()
Der Operator "as?" Wirkt es auf den Typ "Dog" im obigen Beispiel. Wenn es nicht gewirkt werden kann, wird null zurückgegeben, was sicher ist.
Neben dem sicheren Aufrufen (mit .?
) Gibt es eine Möglichkeit, mit nulltoleranten Typen umzugehen.
val num: Int? = //Kann null sein
val floatNum = num.toFloat() //Kompilierungsfehler
val floatNum = num!!.toFloat() //Kompilieren Sie OK, aber mögliche NullPointerException
Fügen Sie . !!
hinzu.
Es gibt einige Situationen, in denen dies erforderlich ist, es sollte jedoch nicht so oft wie möglich verwendet werden.
Sie werden diese Art der Verzweigung häufig in Java sehen.
// Java
Dog dog = getDog(); //Der Rückgabewert von getDog kann null sein
if (dog == null) {
dog = new Dog();
}
dog.run();
kotlin hat einen Operator, der nützlich ist, wenn "wenn es null ist".
val dog = getDog() ?: Dog()
dog.run()
?:
Elvis-Operator
Nulltolerante Variablen links
Beschreiben Sie auf der rechten Seite den auszuführenden Prozess, wenn er null ist.
Es ist üblich, alternative Objekte zu erstellen und Ausnahmen auszulösen.
Wenn Sie eine Eigenschaft einer Klasse deklarieren, müssen Sie sie möglicherweise zu einem nullbaren Typ machen. Framework-Klassen, die Konstruktoren nicht überschreiben können, Eigenschaften, die erst nach einem bestimmten Rückruf initialisiert werden können ...
Die Arbeit mit nulltoleranten Typen ist jedoch normalerweise umständlich, und Sie möchten sie möglicherweise mit praktisch nicht nulltoleranten Typen behandeln. (Oft tatsächlich mit Kotlin entwickelt)
In einem solchen Fall ist der Modifikator "lateinit" praktisch.
//Klasse für Login anzeigen
class LoginView {
//Es hat untergeordnete Elemente wie TextView und Button,
//Diese werden aus Ressourcen generiert...Virtuelles UI-System
lateinit var emailTextView: TextView
lateinit var passwordTextView: TextView
lateinit var loginButton: Button
//Untergeordnete Elemente können abgerufen werden, wenn View aus einer Ressource geladen wird
fun onLoadViewFromResource(viewResource: View) {
this.emailTextView = viewResource.children[0]
this.passwordTextView = viewResource.children[1]
this.loginButton = viewResource.children[2]
}
}
Der Modifikator "lateinit" kann die Initialisierung verzögern. Beachten Sie, dass der Zugriff auf die Eigenschaft vor der Initialisierung zu einer Ausnahme führt.
Darüber hinaus gibt es einen Eigenschaftendelegierten namens "faul". Dies ist nützlich für die verzögerte Initialisierung von Eigenschaften, deren Initialisierung teuer ist.
class LoginView {
val loginConnection: LoginConnection by lazy {
LoginConnection() //Die Generierung von LoginConnection ist teuer
}
}
Recommended Posts