java-inferencia-tipos-var

Inferencia de tipos en Java: la palabra clave var

  • 4 min

La inferencia de tipos permite que el compilador deduzca el tipo estático de una variable local a partir de su inicializador.

Si vienes siguiendo el curso, en el artículo anterior fuimos muy pesados con que Java es de tipado fuerte y estático. Dijimos que hay que declarar el tipo de todo:

String saludo = "Hola Mundo";
int numero = 42;
URL url = new URL("https://luisllamas.es");
Copied!

Esto está muy bien porque es explícito, pero a veces, especialmente en nombres de clases largos, se vuelve redundante. El compilador de Java es listo. Si a la derecha del igual hay un texto "Hola Mundo", el compilador ya sabe que eso es un String. ¿Por qué obligarnos a escribirlo dos veces?

Para solucionar esto, tenemos la palabra clave var.

¿Qué es var?

var nos permite declarar variables locales sin especificar su tipo explícitamente, dejando que el compilador “infiera” (deduzca) el tipo basándose en el valor que le asignamos.

Veamos el cambio:

// Forma Clásica (Java 9 e inferiores)
String mensaje = "Hola a todos";
int contador = 0;
ByteArrayOutputStream output = new ByteArrayOutputStream();

// Forma Moderna (Java 10+)
var mensaje = "Hola a todos";  // El compilador sabe que es String
var contador = 0;              // El compilador sabe que es int
var output = new ByteArrayOutputStream(); // El compilador sabe lo que es
Copied!

Importante: var NO es un tipo de dato. Es una instrucción para el compilador que dice: “mira lo que hay a la derecha del igual y ponle ese tipo a la variable”.

Lo que var no es

El uso de var no rompe el tipado estático. La variable sigue teniendo un tipo fijo, solo que no lo escribes tú.

Una vez que el compilador decide que es un String, será String para siempre.

var precio = 10.5; // El compilador decide que 'precio' es double

precio = 20.0;     // Correcto, sigue siendo double
precio = "Caro";   // ¡ERROR DE COMPILACIÓN! No puedes meter un String en un double.
Copied!

Limitaciones: ¿dónde puedo usarlo?

La inferencia de tipos en Java es conservadora. No vale para todo. Solo puedes usar var en variables locales inicializadas.

Obligatorio inicializar

El compilador necesita saber el valor para deducir el tipo.

var nombre;          // ERROR: ¿Qué tipo es? No lo sé.
var nombre = "Luis"; // Correcto.
Copied!

No se permiten nulos directos

null no tiene tipo (puede ser cualquier objeto), así que el compilador no sabe qué hacer.

var objeto = null;         // ERROR
var objeto = (String)null; // Funciona (pero es absurdo)
Copied!

Solo en variables locales

No puedes usar var para atributos de una clase (campos) ni para parámetros de métodos.

public class Usuario {
    var nombre = "Pepe"; // ERROR: No permitido en atributos de clase

    public void saludar(var texto) { // ERROR: No permitido en parámetros
        // ...
    }
}
Copied!

La razón es que los atributos y métodos definen la API pública de tu clase y deben ser explícitos para que otros sepan cómo usarlos sin tener que leer el código interno.

¿Cuándo usar var?

Aquí viene el debate eterno. ¿Deberíamos usar var siempre?

El código se lee más veces de las que se escribe. El objetivo de var es reducir el ruido visual, no ocultar información importante.

✅ Cuándo sí usarlo

  1. Cuando la declaración es redundante:
// Repetitivo y ruidoso
FileInputStream fis = new FileInputStream("archivo.txt");

// Limpio y claro
var fis = new FileInputStream("archivo.txt");
Copied!
  1. En bucles for-each:
for (var usuario : listaDeUsuarios) {
    // ...
}
Copied!
  1. Con nombres de tipos genéricos complejos: Aquí es donde var brilla.
// Dolor de ojos
Map<String, List<Map<Integer, String>>> datos = new HashMap<>();

// Paz mental
var datos = new HashMap<String, List<Map<Integer, String>>>();
Copied!

❌ Cuándo no usarlo

Cuando el tipo no es evidente viendo el lado derecho.

var resultado = procesarDatos(); // ¿Qué devuelve esto? ¿Un int? ¿Un String? ¿Un Objeto?
Copied!

En este caso, estás obligando al lector (o a ti mismo dentro de 3 meses) a navegar al método procesarDatos() para saber qué demonios es resultado. Aquí es mucho mejor ser explícito:

ResultadoProceso resultado = procesarDatos();
Copied!