La nullableitat és la capacitat d’una variable de contenir un valor null
- Introducció
- Non-null types
- Nullable types
- Gestió de variables nullable
- Utilitza l’operador d’accés segur ?.
- TODO
Introducció
Un valor null
representa “cap valor” o dades “desconegudes/absents”. No és zero, ni una cadena buida, ni false
: és l’absència intencional d’un valor.
Non-null types
Els tipus no nuls són variables que no poden contenir null
.
Quan declares una variable, li has d’assignar un valor immediatament.
Per exemple, quan declares una variable name
, pots assignar-li immediatament el valor de tipus string “Laura”.
fun main() {
var name = "Laura"
}
Ha Kotlin - Computació vas aprendre que pots reasssignar variables definides amb la paraula clau var
a diferents valors del mateix tipus.
Per exemple, pots reasssignar la variable name
que s’ha declarat amb un nom a un altre nom, sempre que el nou nom sigui de tipus String
.
fun main() {
var name: String = "Laura"
name = "mireia"
}
Que passa si vull reassignar el valor de name
a null
:
var name = "Laura"
name = null
El compilador dona un error:
Null cannot be a value of a non-null type 'String'.
Un tipus només és nullable si explícitament li permets contenir null
.
Tal com diu el missatge d’error, el tipus de dades String
és un tipus no nullable, així que no pots reasssignar la variable a null
.
Per tant, puc estar segur que sempre que escrigui aquest codi la variable name
tindrà un valor:
var name: String = "Laura"
nane = someName()
name.lowercase()
Nullable types
Els tipus nuls són variables que poden contenir null
.
Si al principi no tens cap nom, el més lógic és escriure aquest codi:
var name = null
Que passa si vols reassignar el valor de name
a "Mireia"
?
var name = null
name = "Mireia"
El compilador dona un error:
Assignment type mismatch: actual type is 'String', but 'Nothing?' was expected.
Per declarar variables nullable a Kotlin, cal afegir l’operador ?
al final del tipus.
Per exemple, un tipus String?
pot contenir un string o null
, mentre que un tipus String
només pot contenir una string.
Per declarar una variable nullable, has d’afegir explícitament el tipus nullable.
var name: String? = null
name = "Laura"
I com que la variable name
pot tenir un valor null
, aquest codi no és segur:
var name: String? = "Laura"
name.lowercase()
El codi no és correcte encara que name
tingui el valor "Laura"
:
Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'String?'.
Primer has de verificar que la variable name
té un valor:
var name: String? = "Laura"
if (name != null)
name.lowercase()
Com que en Kotlin tot són objectes, les variables numèriques també poden ser nullables:
var number: Int? = null
number = 30
if (number != null)
number += 1
Gestió de variables nullable
Accedir a una propietat d’una variable nullable
Fem servir l’operador .
per accedir a mètodes i propietats de variables no nullables.
Però amb variables que poden tenir el valor null
no ho pots fer:
var name: String? = null
name.lowercase()
Com has vist abans, obtindràs aquest missatge d’error:
Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'String?'.
Aquest error és un error de compilació que passa quan Kotlin no pot compilar el codi a causa d’un error de sintaxi en el teu codi.
Kotlin aplica intencionadament regles sintàctiques per aconseguir la seguretat contra valors nuls (null
safety), que fa referència a la garantia que no es fan crides accidentals sobre variables potencialment nul·les. Això no vol dir que les variables no puguin ser nul·les. Vol dir que, si s’accedeix a un membre d’una variable, la variable no pot ser nul·la.
Això és crític perquè si s’intenta accedir a un membre d’una variable que és nul·la — conegut com a referència nul·la — durant l’execució d’una app, l’app es bloqueja perquè la variable nul·la no conté cap propietat ni mètode. Aquest tipus de bloqueig és un error en temps d’execució, en què l’error es produeix després que el codi s’hagi compilat i s’estigui executant.
A causa de la naturalesa “null
safety” de Kotlin, aquests errors en temps d’execució es prevenen perquè el compilador de Kotlin força una comprovació de nul·litat per als tipus nullable. La comprovació de nul·litat fa referència al procés de verificar si una variable podria ser nul·la abans d’accedir-hi i tractar-la com un tipus no nullable. Si vols utilitzar un valor nullable com si fos el seu tipus no nullable, has de fer explícitament una comprovació de nul·litat com veurem més endavant sobre l’ús de condicionals if/else.
En aquest exemple, el codi falla en temps de compilació perquè no es permet la referència directa a la propietat lowercase
de la variable name
, ja que hi ha la possibilitat que la variable sigui nul·la.
A continuació, aprendràs diverses tècniques i operadors per treballar amb tipus nullable.
Utilitza l’operador d’accés segur ?.
Pots utilitzar l’operador d’accés segur ?.
per accedir a mètodes o propietats de variables nullable.
Per utilitzar l’operador ?.
per accedir a un mètode o propietat, afegeix un símbol ?
després del nom de la variable i accedeix al mètode o propietat amb la notació .
.
fun main() {
var name: String? = null
require( name?.lowercase() == null )
}
Observa que el programa no es bloqueja tot i l’intent d’accedir a la propietat length d’una variable nul·la. L’expressió d’accés segur simplement retorna null.
L’operador d’accés segur ?.
permet un accés més segur a variables nullable perquè el compilador de Kotlin evita qualsevol intent d’accedir a membres sobre referències null
i retorna null
per al membre accedit.
També pots utilitzar l’operador d’accés segur ?.
en variables no nul·les per accedir a un mètode o una propietat. Tot i que el compilador de Kotlin no donarà cap error per això, no és necessari perquè l’accés a mètodes o propietats de variables no nul·les és sempre segur.
var name: String = "Laura"
require( name?.lowercase() == "laura" )
El compilador Kotlin ja t’avisa que no fa falta utilitzar l’operador ?
, però et deixa fer si és el que vols 👻:
Unnecessary safe call on a non-null receiver of type `String'.
Use the !! not-null assertion operator
You can also use the !!
not-null assertion operator to access methods or properties of nullable variables.
After the nullable variable, you need to add the !!
not-null assertion operator followed by the .
operator and then the method or property without any spaces.
fun main() {
var name: String? = "Laura"
val laura: String = name!!
require(laura.lowercase() == "laura")
}
As the name suggests, if you use the !!
not-null assertion, it means that you assert that the value of the variable isn’t null, regardless of whether it is or isn’t.
fun main() {
var name: String? = null
val laura: String = name!!
require(laura.lowercase() == "laura")
}
Unlike ?.
safe-call operators, the use of a !!
not-null assertion operator may result in a NullPointerException
error being thrown if the nullable variable is indeed null.
Exception in thread "main" java.lang.NullPointerException
at MainKt.main(Main.kt:3)
at MainKt.main(Main.kt)
Aquest error de Kotlin mostra que el teu programa s’ha bloquejat durant l’execució. Per tant, no es recomana utilitzar l’operador d’afirmació de no nul·litat !!
llevat que estiguis segur que la variable no és nul·la.
Així doncs, només s’hauria de fer quan la variable és sempre no nul·la o hi ha implementada una gestió d’excepcions adequada. Quan no es gestionen, les excepcions provoquen errors en temps d’execució. Aprendràs la gestió d’excepcions a Kotlin - Excepcions.
Utilitza les condicionals if/else
Pots utilitzar la branca if
dins de les condicionals if/else
per fer comprovacions de nul·litat.
Per fer comprovacions de nul·litat, pots verificar que la variable nullable no és igual a null
amb l’operador de comparació !=
.
Una sentència if/else es pot utilitzar juntament amb una comprovació de null
de la manera següent:
fun main() {
var name: String? = null
val lower = if (name != null) name.lowercase() else "desconegut"
require(lower == "desconegut")
}
-
La comprovació de nul·litat de l’expressió
name != null
s’utilitza com a condició de l’if
. -
El cos dins de la branca
if
assumeix que la variable no és nul·la. Per tant, en aquest cos, pots accedir lliurement als mètodes o propietats de la variable com si fos no nullable, sense utilitzar l’operador d’accés segur?.
ni l’operador d’afirmació de no nul·litat!!
. -
El cos dins de la branca
else
assumeix que la variable ésnull
. Per tant, en aquest cos, pots afegir sentències que s’han d’executar quan la variable ésnull
. La brancaelse
és opcional. Pots utilitzar només la condicionalif
per fer una comprovació denull
sense proporcionar una acció per defecte quan la comprovació falla.
La comprovació de nul·litat és més convenient amb la condició if
quan hi ha múltiples línies de codi que utilitzen la variable nullable. En canvi, l’operador d’accés segur ?.
és més convenient per a una única referència de la variable nullable.
També pots utilitzar l’operador de comparació ==
per a comprovacions de nul·litat en lloc de l’operador !=
. En fer-ho, tingues en compte que els dos cossos s’inverteixen. El cos de la branca if
assumeix que la variable és null
i el cos de la branca else
assumeix que la variable no és null
.
fun main() {
var name: String? = null
val lower = if (name == null) "desconegut" else name.lowercase()
require(lower == "desconegut")
}
Utilitza l’operador Elvis ?:
L’operador Elvis ?:
és un operador que pots utilitzar juntament amb l’operador d’accés segur ?.
.
Amb l’operador Elvis ?:
, pots afegir un valor per defecte quan l’operador d’accés segur ?.
retorna null
. És similar a una expressió if/else
, però d’una manera més idiomàtica.
fun main() {
var name: String? = null
require(name?.lowercase() == null)
require((name?.lowercase() ?: "desconegut") == "desconegut")
}
Si la variable no és nul·la, s’executa l’expressió anterior a l’operador Elvis ?:
. Si la variable és null
, s’executa l’expressió posterior a l’operador Elvis ?:
.
fun main() {
var name: String? = null
require((name?.lowercase() ?: "desconegut") == "mireia")
}