141 votes

Meilleure façon de vérifier la nullité en Kotlin ?

Dois-je utiliser le double = ou triple = ?

if(a === null)  {
//do something
}

ou

if(a == null)  {
//do something
}

De même pour les "non égaux" :

if(a !== null)  {
//do something
}

ou

if(a != null)  {
//do something
}

1 votes

Regardez le lien :- kotlinlang.org/docs/reference/null-safety.html .............. C'est facile dans Kotlin Docs

214voto

Benito Bertoli Points 9458

Une égalité structurelle a == b est traduit en

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

Par conséquent, si l'on compare avec null l'égalité structurelle a == null est traduit en une égalité référentielle a === null .

Selon le docs il ne sert à rien d'optimiser votre code, vous pouvez donc utiliser a == null et a != null

Note que si la variable est une propriété mutable, vous ne pourrez pas la convertir en son type non-nul à l'intérieur de l'objet if (parce que la valeur pourrait avoir été modifiée par un autre thread) et vous devriez utiliser l'opérateur d'appel sécurisé avec l'instruction let à la place.

Opérateur d'appel sécurisé ?.

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

Vous pouvez l'utiliser en combinaison avec l'opérateur Elvis.

Opérateur Elvis ?: (Je suppose parce que la marque d'interrogatoire ressemble aux cheveux d'Elvis)

a ?: println("null")

Et si vous voulez exécuter un bloc de code

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

Combiner les deux

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")
}

2 votes

Pourquoi n'utilisez-vous pas if pour les contrôles de nullité ? a?.let{} ?: run{} n'est approprié que dans de rares cas, sinon il n'est pas idiomatique.

2 votes

@voddan je ne suggérais pas de ne pas utiliser if pour null des contrôles, je listais d'autres options viables. Bien que je ne sois pas sûr que run a une sorte de pénalité de performance. Je vais mettre à jour ma réponse pour la rendre plus claire.

3 votes

@voddan Si a est un var puis en utilisant le a?.let{} ?: run{} garantir qu'il sera lié correctement dans le let pour toute la portée. Si a est un val alors il n'y a pas de différence.

78voto

Levon Petrosyan Points 1012

Manière dont Kotlin traite les nullités

Opération d'accès sécurisé

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

Soit la fonction

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

Sortie anticipée

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

Ombres immuables

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
}

Valeur par défaut

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

Utiliser val au lieu de var

val est en lecture seule, var est mutable. Il est recommandé d'utiliser le plus grand nombre possible de propriétés en lecture seule, car elles sont à l'abri des conflits.

Utiliser lateinit

Parfois, vous ne pouvez pas utiliser des propriétés immuables. Par exemple, cela arrive sur Android lorsqu'une propriété est initialisée en onCreate() appel. Pour ces situations, Kotlin dispose d'une fonctionnalité du langage appelée 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()
}

69voto

Michael Points 16659

Les deux approches génèrent le même bytecode, vous pouvez donc choisir celle que vous préférez.

7 votes

Si j'ai bien compris, il demande quelle est la meilleure façon de vérifier les nullités en Kotlin, et non quelle approche génère le meilleur byte-code. La réponse de @BenitoBertoli semble prometteuse, mais elle réduit le code passe-partout.

18voto

BingLi224 Points 135

Addition à @Benito Bertoli,

la combinaison est en fait différente de if-else

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

Le résultat est :

1. it=test

Mais si :

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

Le résultat est :

1. it=test
2. it is null!

Aussi, si on utilise Elvis en premier :

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

Le résultat est :

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

5voto

Vlad Points 113

Vérifiez les méthodes utiles, cela pourrait être utile :

/**
 * 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
}

Vous trouverez ci-dessous un exemple possible d'utilisation de ces fonctions :

var s: String? = null

// ...

if (s.isNotNullAndSatisfies{ isEmpty() }{
   // do something
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X