Der beste Weg, um in Kotlin null einzuchecken?


Antworten:


60

Beide Ansätze generieren denselben Bytecode, sodass Sie auswählen können, was Sie bevorzugen.


2
. Wenn ich es richtig verstanden , dann ist er für die beste Möglichkeit zu überprüfen , null in Kotlin fragt, nicht , welcher Ansatz erzeugt besten Byte-Code @ BenitoBertoli Antwort sieht vielversprechend aus , reduziert es vorformulierten Code
imgs

144

Eine strukturelle Gleichheit a == bwird übersetzt in

a?.equals(b) ?: (b === null)

Im Vergleich zu nullwird daher die strukturelle Gleichheit a == nullin eine referentielle Gleichheit übersetzt a === null.

Laut den Dokumenten macht es keinen Sinn, Ihren Code zu optimieren. Sie können also Folgendes verwenden a == nullund a != null


beachten : Wenn die Variable eine veränderbare Eigenschaft ist, können Sie sie nicht intelligent in den nicht nullbaren Typ innerhalb der ifAnweisung umwandeln (weil Der Wert wurde möglicherweise von einem anderen Thread geändert let. Stattdessen müssen Sie den Operator für sichere Anrufe verwenden.

Sicherer Anrufbetreiber ?.

a?.let {
   // not null do something
   println(it)
   println("not null")
}


Sie können es in Kombination mit dem Elvis-Operator verwenden.

Elvis-Operator ?: (Ich vermute, weil das Verhörzeichen wie Elvis 'Haare aussieht)

a ?: println("null")

Und wenn Sie einen Codeblock ausführen möchten

a ?: run {
    println("null")
    println("The King has left the building")
}

Die beiden kombinieren

a?.let {
   println("not null")
   println("Wop-bop-a-loom-a-boom-bam-boom")
} ?: run {
    println("null")
    println("When things go null, don't go with them")
}

1
Warum verwenden Sie nicht iffür Nullprüfungen? a?.let{} ?: run{}ist nur in seltenen Fällen angebracht, sonst ist es nicht idiomatisch
voddan

2
@voddan Ich habe nicht vorgeschlagen, nicht zu verwenden, wenn für nullÜberprüfungen, ich habe andere praktikable Optionen aufgelistet . Obwohl ich nicht sicher bin, ob runes irgendeine Art von Leistungsstrafe gibt. Ich werde meine Antwort aktualisieren, um es klarer zu machen.
Benito Bertoli

1
@voddan Wenn aist ein var, dann mit der a?.let{} ?: run{}Garantie, dass es in der letfür den gesamten Umfang richtig gebunden wird . Wenn a aist val, gibt es keinen Unterschied.
Madeinqc

1
@madeinqc Wenn a a ist val, dann ist die Verwendung von let anders und es ist schlecht. Ich fand diesen Artikel sehr gut darin, ihn zu erklären - Kotlin: Verwenden Sie LET nicht nur für die Nullprüfung .
Sufian

31

Kotlin Umgang mit Null

Sicherer Zugriff

val dialog : Dialog? = Dialog()
dialog?.dismiss()  // if the dialog will be null,the dismiss call will be omitted

Funktionieren lassen

user?.let {
  //Work with non-null user
  handleNonNullUser(user)
}

Vorzeitiger Ausstieg

fun handleUser(user : User?) {
  user ?: return //exit the function if user is null
  //Now the compiler knows user is non-null
}

Unveränderliche Schatten

var user : User? = null

fun handleUser() {
  val user = user ?: return //Return if null, otherwise create immutable shadow
  //Work with a local, non-null variable named user
}

Standardwert

fun getUserName(): String {
 //If our nullable reference is not null, use it, otherwise use non-null value 
 return userName ?: "Anonymous"
}

Verwenden Sie val anstelle von var

valist schreibgeschützt, varist veränderlich. Es wird empfohlen, so viele schreibgeschützte Eigenschaften wie möglich zu verwenden. Sie sind threadsicher.

Verwenden Sie lateinit

Manchmal können Sie keine unveränderlichen Eigenschaften verwenden. Dies geschieht beispielsweise unter Android, wenn eine Eigenschaft beim onCreate()Aufruf initialisiert wird . Für diese Situationen verfügt Kotlin über eine Sprachfunktion namens lateinit.

private lateinit var mAdapter: RecyclerAdapter<Transaction>

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   mAdapter = RecyclerAdapter(R.layout.item_transaction)
}

fun updateTransactions() {
   mAdapter.notifyDataSetChanged()
}

Ich würde den letzten "Standardwert" nennen (nicht elvis), da 3/4 davon elvis verwenden.
AjahnCharles

@ AjahnCharles macht Sinn))
Levon Petrosyan

7

Ergänzung zu @Benito Bertoli,

Die Kombination ist eigentlich anders als wenn-sonst

"test" ?. let {
    println ( "1. it=$it" )
} ?: let {
    println ( "2. it is null!" )
}

Das Ergebnis ist:

1. it=test

Aber falls:

"test" ?. let {
    println ( "1. it=$it" )
    null // finally returns null
} ?: let {
    println ( "2. it is null!" )
}

Das Ergebnis ist:

1. it=test
2. it is null!

Wenn Sie zuerst elvis verwenden:

null ?: let {
    println ( "1. it is null!" )
} ?. let {
    println ( "2. it=$it" )
}

Das Ergebnis ist:

1. it is null!
2. it=kotlin.Unit

5

Schauen Sie sich nützliche Methoden an, es könnte nützlich sein:

/**
 * Performs [R] when [T] is not null. Block [R] will have context of [T]
 */
inline fun <T : Any, R> ifNotNull(input: T?, callback: (T) -> R): R? {
    return input?.let(callback)
}

/**
 * Checking if [T] is not `null` and if its function completes or satisfies to some condition.
 */
inline fun <T: Any> T?.isNotNullAndSatisfies(check: T.() -> Boolean?): Boolean{
    return ifNotNull(this) { it.run(check) } ?: false
}

Nachfolgend finden Sie ein mögliches Beispiel für die Verwendung dieser Funktionen:

var s: String? = null

// ...

if (s.isNotNullAndSatisfies{ isEmpty() }{
   // do something
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.