Kotlin
Null säkerhet
Sök…
Nullable och Non-Nullable typer
Normala typer, som String
, är inte nollbara. För att de ska kunna hålla nollvärden måste du uttryckligen ange det genom att sätta en ?
bakom dem: 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!
Säker samtaloperatör
För att få åtkomst till funktioner och egenskaper för nollbara typer måste du använda speciella operatörer.
Den första ?.
, ger dig egenskapen eller funktionen du försöker få åtkomst till, eller den ger dig noll om objektet är noll:
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.
Idiom: anropa flera metoder på samma, nollkontrollerade objekt
Ett elegant sätt att kalla flera metoder för ett nollkontrollerat objekt använder Kotlins apply
så här:
obj?.apply {
foo()
bar()
}
Detta kommer att ringa foo
och bar
på obj
(vilket är this
i apply
) endast om obj
är icke-null, hoppar över hela blocket annars.
För att få en nullable variabel till räckvidd som en icke-nullable referens utan att göra det till den implicita mottagaren av funktions- och fastighetssamtal kan du använda let
istället för att apply
:
nullable?.let { notnull ->
notnull.foo()
notnull.bar()
}
notnull
kan namnges vad som helst, eller till och med utelämnas och används genom den implicita lambda parameter it
.
Smarta kast
Om kompilatorn kan dra slutsatsen att ett objekt inte kan vara noll vid en viss punkt behöver du inte använda de speciella operatörerna längre:
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!
}
Obs: Kompilatorn tillåter inte att du använder smarta gjutbara variabler som potentiellt kan ändras mellan nollkontrollen och den avsedda användningen.
Om en variabel är tillgänglig utanför ramen för det aktuella blocket (eftersom de till exempel är medlemmar i ett icke-lokalt objekt), måste du skapa en ny, lokal referens som du sedan kan smarta cast och använda.
Ta bort nollor från en Iterable och matris
Ibland måste vi ändra typ från Collection<T?>
Till Collections<T>
. I så fall är filterNotNull
vår lösning.
val a: List<Int?> = listOf(1, 2, 3, null)
val b: List<Int> = a.filterNotNull()
Null Coalescing / Elvis Operator
Ibland är det önskvärt att utvärdera ett nollbart uttryck på ett annat sätt. Elvis-operatören, ?:
, Kan användas i Kotlin för en sådan situation.
Till exempel:
val value: String = data?.first() ?: "Nothing here."
Uttrycket ovan returnerar "Nothing here"
om data?.first()
eller data
sig ger ett null
annars resultatet av data?.first()
.
Det är också möjligt att kasta undantag med samma syntax för att avbryta körning av kod.
val value: String = data?.second()
?: throw IllegalArgumentException("Value can't be null!")
Påminnelse: NullPointerExceptions kan kastas med hjälp av påståendeoperatören (t.ex.
data!!.second()!!
)
Påstående
!!
suffix ignorerar nollbarhet och returnerar en icke-null-version av den typen. KotlinNullPointerException
kastas om objektet är ett null
.
val message: String? = null
println(message!!) //KotlinNullPointerException thrown, app crashes
Elvis Operator (? :)
I Kotlin kan vi förklara variabel som kan innehålla null reference
. Anta att vi har en nolllable referens a
, vi kan säga "om a
inte är noll, använd den, annars använd något icke-nollvärde x
"
var a: String? = "Nullable String Value"
Nu, a
kan vara null. Så när vi måste komma åt värdet på a
, måste vi utföra säkerhetskontroll, oavsett om det innehåller värde eller inte. Vi kan utföra denna säkerhetskontroll genom konventionellt if...else
uttalande.
val b: Int = if (a != null) a.length else -1
Men här kommer förskottoperatören Elvis
(operatören Elvis ?:
:). Ovan if...else
kan uttryckas med Elvis-operatören enligt nedan:
val b = a?.length ?: -1
Om uttrycket till vänster om ?:
( a?.length
: a?.length
) inte är noll, returnerar elvis-operatören det, annars returnerar det uttrycket till höger (här: -1
). Uttrycket på höger sida utvärderas endast om vänster sida är noll.