El operador de llamada segura '?.' es una de las herramientas clave para lidiar con valores nulos en Kotlin y surgió como una evolución de ideas del lenguaje, orientadas a aumentar la seguridad y la comodidad de trabajar con valores potencialmente ausentes.
Contexto: En Java, los valores nulos a menudo se convierten en una fuente de errores (NullPointerException). Kotlin introdujo un sistema de tipos estricto con una clara diferenciación entre variables nullable y not-nullable, acompañado de herramientas para su uso conveniente.
Problema: ¿Cómo evitar NullPointerException al trabajar con objetos que pueden ser nulos, sin sacrificar la legibilidad y concisión del código?
Solución: El operador '?.' permite acceder delicadamente a propiedades y métodos de variables nullable: si el objeto no es nulo, se realiza la llamada; si es nulo, se devuelve nulo (o se ejecuta la lógica necesaria a continuación).
Ejemplo de código:
val user: User? = getUser() val name = user?.name // si user != null, devuelve user.name, de lo contrario nulo user?.printInfo() // si user != null, se llamará a printInfo()
Características clave:
¿Se puede usar el operador de llamada segura '?.' a la izquierda de una asignación?
No. El operador '?.' no se puede usar para establecer de forma segura el valor de una propiedad o variable; solo se aplica para el acceso o la llamada. Lo siguiente es incorrecto:
user?.name = "Alex" // Error de compilación
Se puede realizar la asignación de propiedades de forma segura a través de una verificación explícita:
user?.let { it.name = "Alex" }
¿Qué devuelve una cadena de operadores de llamada segura al encontrar el primer nulo?
Tan pronto como uno de los elementos de la cadena '?.' es nulo, el resultado de la expresión se convierte en nulo, y las llamadas seguras posteriores no se ejecutan.
Ejemplo:
user?.address?.zipCode // si user o address == null, el resultado es nulo
¿Se puede usar la llamada segura '?.' con funciones que devuelven Unit?
Sí, la llamada aún ocurrirá solo si el objeto no es nulo, y devolverá nulo en lugar de Unit si el objeto es nulo.
Ejemplo:
user?.clearData() // si user == null, no ocurrirá nada
Un desarrollador aplica '!!' donde el objeto podría ser nulo, después de una larga cadena de llamada segura:
val country = user?.address?.city?.country!!
Pros:
Contras:
Se usa la llamada segura junto con el operador Elvis para devolver un valor predeterminado:
val country = user?.address?.city?.country ?: "Desconocido"
Pros:
Contras: