CodeGym /Cursos /JAVA 25 SELF /Pattern Matching for instanceof

Pattern Matching for instanceof

JAVA 25 SELF
Nivel 65, Lección 1
Disponible

1. El problema del instanceof clásico

Empecemos con un poco de nostalgia. Antes de Java 16, cuando necesitabas comprobar el tipo de un objeto y luego usarlo como ese tipo, tenías que escribir una plantilla verbosa con una comprobación instanceof y una conversión explícita:

Object obj = ...; // algún objeto

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println("Longitud de la cadena: " + s.length());
}

Un patrón aburrido pero frecuente

Este patrón aparece con mucha frecuencia — manejadores de eventos, trabajo con colecciones heterogéneas, lógica de negocio con herencia, etc.

Por qué es incómodo

  • Duplicación de código — hay que indicar el tipo dos veces: en instanceof y en la conversión.
  • Riesgo de error — es fácil convertir por accidente a un tipo incorrecto y obtener ClassCastException.
  • Código «ruidoso» — empeora la legibilidad, especialmente con múltiples comprobaciones.

2. Pattern Matching for instanceof: nueva sintaxis

En Java 16 se añadió el emparejamiento por patrones (pattern matching) para instanceof. Ahora comprobamos el tipo y declaramos inmediatamente una variable del tipo necesario, disponible dentro de la rama if.

Nueva sintaxis

if (obj instanceof String s) {
    // ¡s ya es una cadena!
    System.out.println("Longitud de la cadena: " + s.length());
}
  • Después del tipo en instanceof se escribe el nombre de la nueva variable: String s.
  • La variable sólo está disponible dentro del bloque donde la condición es verdadera.
  • No hace falta escribir la conversión (String) — el compilador lo garantiza.

¿Dónde está la magia? El compilador comprueba el tipo y, si encaja, hace disponible la variable del tipo necesario. En caso contrario, el bloque simplemente no se ejecuta.

Cómo se ve en código real

Object obj = "Hola, Java 16+!";

if (obj instanceof String s) {
    System.out.println("Mayúsculas: " + s.toUpperCase());
} else {
    System.out.println("¡Esto no es una cadena!");
}

3. Seguridad y legibilidad: por qué es genial

Se evita el error ClassCastException

Object obj = 123;
// String s = (String) obj; // ¡Boom! Excepción.

Con el pattern matching, la variable se crea solo cuando la comprobación de tipo tiene éxito — sencillamente no hay conversión «incorrecta».

El código se vuelve más corto y claro
Dos líneas se convierten en una. Menos código «ruidoso» — más fácil de leer y mantener.

Ejemplo: procesamiento de distintos tipos

public static void printInfo(Object obj) {
    if (obj instanceof String s) {
        System.out.println("Cadena de longitud " + s.length());
    } else if (obj instanceof Integer i) {
        System.out.println("Entero: " + (i + 1));
    } else {
        System.out.println("Tipo desconocido: " + obj);
    }
}

4. Ejemplos de uso y matices

Comprobación de varios tipos

Object value = ...;

if (value instanceof String s) {
    System.out.println("Es una cadena: " + s);
} else if (value instanceof Number n) {
    System.out.println("Es un número: " + n);
} else {
    System.out.println("Algo más: " + value);
}

Uso con null
Si el objeto es null, instanceof siempre devolverá false — no habrá NPE, pero el bloque no se ejecutará.

Object obj = null;

if (obj instanceof String s) {
    // Este bloque NUNCA se ejecutará si obj == null
    System.out.println("Cadena: " + s);
} else {
    System.out.println("obj es null o no es una cadena");
}

Pattern matching con herencia

class Animal {}
class Dog extends Animal {
    void bark() { System.out.println("¡Guau!"); }
}

Animal a = new Dog();

if (a instanceof Dog d) {
    d.bark(); // ¡Podemos llamar a los métodos de Dog sin conversión!
}

Recordatorio: el orden de las comprobaciones es importante; ve de lo más específico a lo más general, de lo contrario las comprobaciones «estrechas» pueden no activarse.

Comparación: enfoque antiguo y nuevo

Forma antigua Forma nueva (pattern matching)
if (obj instanceof Cat) {
    Cat c = (Cat) obj;
    c.meow();
}
if (obj instanceof Cat c) {
    c.meow();
}

5. Limitaciones del pattern matching para instanceof

  • Ámbito de la variable. La variable del patrón sólo es visible en la rama donde la comprobación es verdadera.
if (obj instanceof String s) {
    System.out.println(s); // s está disponible
}
// System.out.println(s); // ¡Error! s no es visible aquí
  • No se pueden declarar varias variables de distintos tipos en una misma condición.
// Error de compilación:
if (obj instanceof String s || obj instanceof Integer i) {
    // ...
}
  • Se requiere Java 16+. En versiones más antiguas del JDK, la nueva sintaxis no es compatible.

6. Ejemplos prácticos (sobre una aplicación sencilla)

Imaginemos un gestor de tareas simple con distintos tipos de tareas.

Clases

class Task {
    String title;
    public Task(String title) { this.title = title; }
}

class BugTask extends Task {
    int severity;
    public BugTask(String title, int severity) {
        super(title);
        this.severity = severity;
    }
}

class FeatureTask extends Task {
    String feature;
    public FeatureTask(String title, String feature) {
        super(title);
        this.feature = feature;
    }
}

Procesamiento con pattern matching

public static void processTask(Task t) {
    if (t instanceof BugTask bug) {
        System.out.println("Bug: " + bug.title + ", criticidad: " + bug.severity);
    } else if (t instanceof FeatureTask feature) {
        System.out.println("Funcionalidad: " + feature.title + ", módulo: " + feature.feature);
    } else if (t instanceof Task task) {
        System.out.println("Tarea normal: " + task.title);
    }
}

7. Matices útiles

Tabla: pattern matching para instanceof — pros y contras

Pros Contras/Limitaciones
Menos código, mayor legibilidad Requiere Java 16+
Sin riesgo de ClassCastException La variable sólo es visible dentro del bloque if
Seguridad de tipos a nivel de compilación No funciona para varios tipos en una sola condición
Cómodo para manejar la herencia En IDE y builds antiguos puede no ser compatible
Adecuado para cualquier clase

Esquema visual: cómo funciona el pattern matching para instanceof

+---------------------------+
|      Object obj           |
+---------------------------+
            |
            v
  if (obj instanceof Type t)
            |
       Sí           No
   (true)        (false)
    |               |
    v               v
 t disponible    t no existe
   (código)        (sin acceso)

8. Errores típicos al usar el pattern matching for instanceof

Error n.º 1: intentar usar la variable fuera del bloque if. Se declaró la variable en el patrón, se salió del bloque — la variable ya no existe. El compilador, con razón, se queja: «¿Quién es s?»

Error n.º 2: esperar que instanceof funcione con null. Si el objeto es null, la condición instanceof es siempre falsa y la variable no se crea. Trata null por separado si es necesario.

Error n.º 3: usar la nueva sintaxis en una versión antigua del JDK/IDE. En Java 11 y anteriores, el emparejamiento por patrones para instanceof no está disponible — obtendrás un error de sintaxis. Comprueba tu versión de JDK.

Error n.º 4: confusión con el ámbito. La variable del patrón sólo está disponible en la rama donde la comprobación es verdadera. Fuera de ella, no existe.

Error n.º 5: esperar soporte de varios tipos a la vez. No se pueden declarar dos variables de distintos tipos en una misma condición: if (obj instanceof String s || obj instanceof Integer i) — no se puede. Para cada tipo, su propia comprobación.

1
Tarea
JAVA 25 SELF, nivel 65, lección 1
Bloqueada
Analizador inteligente de datos 🔍
Analizador inteligente de datos 🔍
1
Tarea
JAVA 25 SELF, nivel 65, lección 1
Bloqueada
Identificación de mascotas en el refugio 🐾
Identificación de mascotas en el refugio 🐾
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION