Kotlin
Nulla sicurezza
Ricerca…
Tipi Nullable e Non-Nullable
I tipi normali, come String
, non sono annullabili. Per renderli in grado di contenere valori nulli, devi indicarlo esplicitamente mettendo un ?
dietro di loro: String?
var string : String = "Hello World!" var nullableString: String? = null string = nullableString // Compiler error: Can't assign nullable to non-nullable type. nullableString = string // This will work however!
Operatore di chiamate sicure
Per accedere a funzioni e proprietà di tipi nullable, è necessario utilizzare operatori speciali.
Il primo, ?.
, ti fornisce la proprietà o la funzione a cui stai tentando di accedere, oppure ti dà null se l'oggetto è nullo:
val string: String? = "Hello World!" print(string.length) // Compile error: Can't directly access property of nullable type. print(string?.length) // Will print the string's length, or "null" if the string is null.
Idioma: chiamare più metodi sullo stesso oggetto con controllo null
Un modo elegante per chiamare più metodi di un oggetto con controllo null sta usando Kotlin's apply
questo modo:
obj?.apply {
foo()
bar()
}
Questo chiamerà foo
e bar
su obj
(che è this
nel blocco apply
) solo se obj
non è nullo, altrimenti salterà l'intero blocco.
Per portare una variabile nullable nell'ambito come riferimento non nullable senza renderlo il ricevitore implicito di chiamate di proprietà e di proprietà, è possibile utilizzare let
invece di apply
:
nullable?.let { notnull ->
notnull.foo()
notnull.bar()
}
notnull
potrebbe essere chiamato nulla, o addirittura lasciato fuori e utilizzato attraverso il parametro lambda implicita it
.
Cast intelligenti
Se il compilatore può dedurre che un oggetto non può essere nullo ad un certo punto, non devi più usare gli operatori speciali:
var string: String? = "Hello!"
print(string.length) // Compile error
if(string != null) {
// The compiler now knows that string can't be null
print(string.length) // It works now!
}
Nota: il compilatore non consente di modificare le variabili mutabili intelligenti che potrebbero essere potenzialmente modificate tra il controllo null e l'utilizzo previsto.
Se una variabile è accessibile dall'esterno del blocco corrente (perché sono membri di un oggetto non locale, ad esempio), è necessario creare un nuovo riferimento locale che è possibile utilizzare come cast intelligente.
Elimina i null da un Iterable e array
A volte abbiamo bisogno di cambiare tipo dalla Collection<T?>
Collections<T>
. In tal caso, filterNotNull
è la nostra soluzione.
val a: List<Int?> = listOf(1, 2, 3, null)
val b: List<Int> = a.filterNotNull()
Operatore Null Coalescing / Elvis
A volte è preferibile valutare un'espressione nullable in modo if else. L'operatore elvis, ?:
, Può essere utilizzato in Kotlin per una situazione del genere.
Per esempio:
val value: String = data?.first() ?: "Nothing here."
L'espressione sopra restituisce "Nothing here"
se data?.first()
o data
stessa producono un valore null
altrimenti il risultato di data?.first()
.
È anche possibile generare eccezioni utilizzando la stessa sintassi per interrompere l'esecuzione del codice.
val value: String = data?.second()
?: throw IllegalArgumentException("Value can't be null!")
Promemoria: NullPointerExceptions può essere lanciato usando l' operatore di asserzione (es.
data!!.second()!!
)
Asserzione
!!
i suffissi ignorano il nullability e restituiscono una versione non nulla di quel tipo. KotlinNullPointerException
verrà generato se l'oggetto è null
.
val message: String? = null
println(message!!) //KotlinNullPointerException thrown, app crashes
Operatore Elvis (? :)
In Kotlin, possiamo dichiarare una variabile che può contenere null reference
. Supponiamo di avere un riferimento nullable a
, possiamo dire "se a
non è nullo, usalo, altrimenti usa un valore non nullo x
"
var a: String? = "Nullable String Value"
Ora, a
può essere nullo. Pertanto, quando è necessario accedere al valore di a
, è necessario eseguire un controllo di sicurezza, indipendentemente dal fatto che contenga o meno un valore. Possiamo eseguire questo controllo di sicurezza con la convenzionale istruzione if...else
.
val b: Int = if (a != null) a.length else -1
Ma ecco che arriva operatore anticipo Elvis
(Operatore Elvis: ?:
). Sopra if...else
può essere espresso con l'operatore Elvis come di seguito:
val b = a?.length ?: -1
Se l'espressione a sinistra di ?:
(Qui: a?.length
) non è nulla, l'operatore elvis la restituisce, altrimenti restituisce l'espressione a destra (qui: -1
). L'espressione sul lato destro viene valutata solo se il lato sinistro è nullo.