Kotlin
Seguridad nula
Buscar..
Tipos anulables y no anulables
Los tipos normales, como String
, no son anulables. Para que sean capaces de mantener valores nulos, tiene que denotar explícitamente al poner un ?
detrás de ellos: 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!
Operador de llamada segura
Para acceder a las funciones y propiedades de los tipos anulables, debe utilizar operadores especiales.
El primero, ?.
, le proporciona la propiedad o función a la que intenta acceder o le da un valor nulo si el objeto es nulo:
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: llamar a múltiples métodos en el mismo objeto sin verificar
Una forma elegante de llamar a múltiples métodos de un objeto con comprobación nula es usando las apply
de Kotlin de la siguiente manera:
obj?.apply {
foo()
bar()
}
Esto llamará foo
y bar
en obj
(que es this
en el bloque de apply
) solo si obj
no es nulo, omitiendo todo el bloque de lo contrario.
Para poner una variable anulable dentro del alcance como una referencia no anulable sin convertirla en el receptor implícito de llamadas de función y propiedad, puede usar let
lugar de apply
:
nullable?.let { notnull ->
notnull.foo()
notnull.bar()
}
notnull
podría tener un nombre, o incluso notnull
y usarse a través del parámetro lambda implícito it
.
Moldes inteligentes
Si el compilador puede inferir que un objeto no puede ser nulo en un cierto punto, ya no tiene que usar los operadores especiales:
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: el compilador no le permitirá realizar una conversión inteligente de variables mutables que podrían modificarse entre la comprobación nula y el uso previsto.
Si se puede acceder a una variable desde fuera del alcance del bloque actual (debido a que son miembros de un objeto no local, por ejemplo), debe crear una referencia local nueva que luego pueda realizar una conversión inteligente y usar.
Elimina los nulos de un iterable y un array
A veces necesitamos cambiar el tipo de Collection<T?>
Collections<T>
. En ese caso, filterNotNull
es nuestra solución.
val a: List<Int?> = listOf(1, 2, 3, null)
val b: List<Int> = a.filterNotNull()
Null Coalescing / Elvis Operator
A veces es deseable evaluar una expresión anulable de una manera si no es así. El operador de elvis, ?:
, Se puede usar en Kotlin para tal situación.
Por ejemplo:
val value: String = data?.first() ?: "Nothing here."
La expresión anterior devuelve "Nothing here"
si los data?.first()
o los data
sí mismos arrojan un valor null
o el resultado de los data?.first()
.
También es posible lanzar excepciones utilizando la misma sintaxis para abortar la ejecución del código.
val value: String = data?.second()
?: throw IllegalArgumentException("Value can't be null!")
Recordatorio: las nullPointerExceptions se pueden lanzar mediante el operador de aserción (por ejemplo,
data!!.second()!!
)
Afirmación
!!
los sufijos ignoran la nulabilidad y devuelven una versión no nula de ese tipo. KotlinNullPointerException
lanzará KotlinNullPointerException
si el objeto es un null
.
val message: String? = null
println(message!!) //KotlinNullPointerException thrown, app crashes
Operador Elvis (? :)
En Kotlin, podemos declarar una variable que puede contener una null reference
. Supongamos que tenemos una referencia anulable a
, podemos decir "si a
no es nulo, utilícelo; de lo contrario, use un valor no nulo x
"
var a: String? = "Nullable String Value"
Ahora, a
puede ser nulo. Entonces, cuando necesitamos acceder al valor de a
, debemos realizar una verificación de seguridad, ya sea que contenga valor o no. Podemos realizar esta verificación de seguridad por convencional if...else
declaración.
val b: Int = if (a != null) a.length else -1
Pero aquí viene el operador avanzado Elvis
(operador Elvis ?:
. Más arriba if...else
puede expresarse con el operador de Elvis de la siguiente manera:
val b = a?.length ?: -1
Si la expresión a la izquierda de ?:
(Aquí: a?.length
) no es nula, el operador elvis la devuelve, de lo contrario, devuelve la expresión a la derecha (aquí: -1
). La expresión del lado derecho solo se evalúa si el lado izquierdo es nulo.