← Flutter & Dart

Fundamentos de Dart

¿Qué es null safety en Dart y para qué sirven `?`, `!`, `??` y `late`?

Ver respuesta — intenta responderla en voz alta primero

Null safety significa que, por defecto, una variable no puede ser null a menos que lo digas explícitamente con ?. Esto mueve una familia entera de errores (los famosos NullPointerException) de tiempo de ejecución a tiempo de compilación. ? marca un tipo como nullable, ! afirma que algo no es null, ?? da un valor por defecto y late promete inicializar después.

Antes, cualquier variable podía valer null y el error solo aparecía al ejecutar. Con null safety, String nunca es null; si quieres permitir null, escribes String?.

Los operadores clave:

  • ? (tipo nullable): String? nombre puede ser un texto o null.
  • ?. (acceso seguro): usuario?.nombre devuelve null si usuario es null, en vez de explotar.
  • ?? (valor por defecto): nombre ?? "invitado" usa "invitado" si nombre es null.
  • ??= (asignar si es null): nombre ??= "invitado" asigna solo si nombre era null.
  • ! (null assertion): nombre! le promete al compilador "esto no es null, confía en mí". Si te equivocas, explota en runtime.
  • late: promete que inicializarás la variable antes de usarla. Útil cuando no puedes darle valor en la declaración pero sabes que existirá.
void main() {
  String? nombre; // puede ser null
  print(nombre); // null

  // ?. acceso seguro
  print(nombre?.length); // null (no explota)

  // ?? valor por defecto
  print(nombre ?? "invitado"); // "invitado"

  // ??= asignar solo si es null
  nombre ??= "Mike";
  print(nombre); // "Mike"

  // ! afirma que no es null (úsalo con cuidado)
  String? tal_vez = "hola";
  String seguro = tal_vez!; // OK porque no era null
  print(seguro.length); // 4

  // late: prometo inicializar antes de usar
  late String saludo;
  saludo = "Hola";
  print(saludo); // "Hola"
}

Abusar del operador ! para "callar" al compilador. variable! no verifica nada: si la variable es null en ese momento, tu app explota igual que antes de null safety. El ! debería usarse solo cuando de verdad sabes que el valor existe; en la mayoría de los casos es mejor ?? o una comprobación con if (variable != null).

"Null safety hace que las variables no puedan ser null por defecto; si quiero permitir null, uso ?, como en String?. Eso convierte los errores de null en errores de compilación en lugar de crashes en producción. Para trabajar con nullables tengo ?. para acceso seguro, ?? para dar un valor por defecto, y ! para afirmar que algo no es null, aunque el ! lo evito porque no verifica nada y puede explotar en runtime. late lo uso cuando sé que voy a inicializar la variable más adelante, no en la declaración."

Reto rápido

¿Qué imprime este código?

String? texto;
print(texto?.length ?? -1);
Ver respuesta

Imprime -1. texto es null, así que texto?.length devuelve null (gracias al ?. no explota). Luego ?? -1 reemplaza ese null por -1.