Esta sección fue probado por nuestros especialistas para asegurar la veracidad de nuestro contenido.
Tipos que aceptan valores NULL y tipos no nulos
El sistema de tipos de Kotlin tiene como objetivo eliminar el peligro de null referencias del código, también conocido como El error del billón de dólares.
Uno de los errores más comunes en muchos lenguajes de programación, incluido Java, es que acceder a un miembro de un null referencia dará como resultado una null excepción de referencia. En Java, esto sería el equivalente a un NullPointerException
o NPE para abreviar.
El sistema de tipos de Kotlin tiene como objetivo eliminar NullPointerException
es de nuestro código. Las únicas causas posibles de NPE pueden ser:
- Una llamada explícita a
throw NullPointerException()
; - Uso del
!!
operador que se describe a continuación; - Alguna inconsistencia de datos con respecto a la inicialización, como cuando:
- Un no inicializado esta disponible en un constructor se pasa y se usa en algún lugar (“filtrando esta“);
- Un constructor de superclase llama a un miembro abierto cuya implementación en la clase derivada usa un estado no inicializado;
- Interoperación de Java:
- Intenta acceder a un miembro en un
null
referencia de un tipo de plataforma; - Tipos genéricos utilizados para la interoperación de Java con nulabilidad incorrecta, por ejemplo, un fragmento de código Java podría agregar
null
en un KotlinMutableList
, significa queMutableList
debe usarse para trabajar con él; - Otros problemas causados por el código Java externo.
- Intenta acceder a un miembro en un
En Kotlin, el sistema de tipos distingue entre referencias que pueden contener null (referencias que aceptan valores NULL) y las que no pueden (nonull referencias). Por ejemplo, una variable regular de tipo String
no puede sostener null:
funmain()//sampleStartvar a: String ="abc"// Regular initialization means non-null by default a =null// compilation error//sampleEnd
Para permitir valores nulos, podemos declarar una variable como anulable string, escrito String?
:
funmain()//sampleStartvar b: String?="abc"// can be set null b =null// okprint(b)//sampleEnd
Ahora, si llama a un método o accede a una propiedad en a
, se garantiza que no provocará una NPE, por lo que puede decir con seguridad:
val l = a.length
Pero si desea acceder a la misma propiedad en b
, eso no sería seguro y el compilador informa un error:
val l = b.length // error: variable 'b' can be null
Pero todavía necesitamos acceder a esa propiedad, ¿verdad? Hay varias formas de hacerlo.
Verificando para null en condiciones
Primero, puede verificar explícitamente si b
es nully maneje las dos opciones por separado:
val l =if(b !=null) b.length else-1
El compilador rastrea la información sobre la verificación que realizó y permite que la llamada length
dentro de si. También se admiten condiciones más complejas:
funmain()//sampleStartval b: String?="Kotlin"if(b !=null&& b.length >0)print("String of length $b.length")elseprint("Empty string")//sampleEnd
Tenga en cuenta que esto solo funciona donde b
es inmutable (es decir, una variable local que no se modifica entre la comprobación y el uso o un miembro val que tiene un campo de respaldo y no es reemplazable), porque de lo contrario podría suceder que b
cambios a null después del cheque.
Llamadas seguras
Su segunda opción es el operador de llamada segura, escrito ?.
:
funmain()//sampleStartval a ="Kotlin"val b: String?=nullprintln(b?.length)println(a?.length)// Unnecessary safe call//sampleEnd
Esto vuelve b.length
si b
no es null, y null de lo contrario. El tipo de esta expresión es Int?
.
Las llamadas seguras son útiles en cadenas. Por ejemplo, si Bob, un empleado, puede ser asignado a un departamento (o no), que a su vez puede tener otro empleado como jefe de departamento, entonces para obtener el nombre del jefe de departamento de Bob (si lo hay), escribimos lo siguiente :
bob?.department?.head?.name
Vuelve una cadena así null si alguna de las propiedades que contiene es null.
Para realizar una determinada operación solo paranull valores, puede utilizar el operador de llamada segura junto con let
:
funmain()//sampleStartval listWithNulls: List<String?>=listOf("Kotlin",null)for(item in listWithNulls) item?.letprintln(it)// prints Kotlin and ignores null//sampleEnd
También se puede colocar una llamada segura en el lado izquierdo de una tarea. Entonces, si uno de los receptores de la cadena de llamadas seguras está null, se omite la asignación y la expresión de la derecha no se evalúa en absoluto:
// If either `person` or `person.department` is null, the function is not called: person?.department?.head = managersPool.getManager()
Operador Elvis
Cuando tenemos una referencia anulable b
, podemos decir “si b
no es null, úselo; de lo contrario, utilice algunosnull valor”:
val l: Int =if(b !=null) b.length else-1
Junto con el completo si-expresión, esto se puede expresar con el operador de Elvis, escrito ?:
:
val l = b?.length ?:-1
Si la expresión a la izquierda de ?:
no es null, el operador de elvis lo devuelve; de lo contrario, devuelve la expresión a la derecha. Tenga en cuenta que la expresión del lado derecho se evalúa solo si el lado izquierdo es null.
Tenga en cuenta que, dado que lanzar y regreso son expresiones en Kotlin, también se pueden usar en el lado derecho del operador elvis. Esto puede resultar muy útil, por ejemplo, para comprobar los argumentos de las funciones:
funfoo(node: Node): String?val parent = node.getParent()?:returnnullval name = node.getName()?:throwIllegalArgumentException("name expected")// ...
los !!
Operador
La tercera opción es para los amantes de la NPE: la nonull operador de aserción!!
) convierte cualquier valor en un valor nonull type y lanza una excepción si el valor es null. Podemos escribir b!!
, y esto devolverá un nonull valor de b
(por ejemplo, un String
en nuestro ejemplo) o lanzar una NPE si b
es null:
val l = b!!.length
Por lo tanto, si desea un NPE, puede tenerlo, pero debe solicitarlo explícitamente y no aparece de la nada.
Casts seguros
Los yesos regulares pueden resultar en ClassCastException
si el objeto no es del tipo de destino. Otra opción es usar yesos seguros que regresen null si el intento no tuvo éxito:
val aInt: Int?= a as? Int
Colecciones de tipos que aceptan valores NULL
Si tiene una colección de elementos de un tipo que acepta valores NULL y desea filtrarnull elementos, puede hacerlo utilizando filterNotNull
:
val nullableList: List<Int?>=listOf(1,2,null,4)val intList: List<Int>= nullableList.filterNotNull()
Sección de Reseñas y Valoraciones
Si te apasiona la informática, puedes dejar una crónica acerca de qué te ha gustado de este ensayo.