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

Pattern Matching para instanceof

JAVA 25 SELF
Nível 65, Lição 1
Disponível

1. O problema do instanceof clássico

Vamos começar com um pouco de nostalgia. Antes do Java 16, quando você precisava verificar o tipo de um objeto e depois usá-lo como esse tipo, era preciso escrever um padrão prolixo com a verificação instanceof e um casting explícito:

Object obj = ...; // algum objeto

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println("Tamanho da string: " + s.length());
}

Chato, mas comum

Esse padrão aparece com muita frequência — manipuladores de eventos, trabalho com coleções heterogêneas, regras de negócio com herança etc.

Por que isso é incômodo

  • Duplicação de código — você precisa indicar o tipo duas vezes: em instanceof e no casting.
  • Risco de erro — é fácil fazer um casting para o tipo errado e receber ClassCastException.
  • Código “ruidoso” — piora a legibilidade, especialmente com múltiplas verificações.

2. Pattern Matching para instanceof: nova sintaxe

No Java 16, foi adicionado o pattern matching para instanceof. Agora verificamos o tipo e já declaramos a variável do tipo necessário, disponível dentro do bloco if.

Nova sintaxe

if (obj instanceof String s) {
    // s — já é uma String!
    System.out.println("Tamanho da string: " + s.length());
}
  • Depois do tipo em instanceof escrevemos o nome da nova variável: String s.
  • A variável fica disponível apenas dentro do bloco em que a condição é verdadeira.
  • Não é preciso escrever o casting (String) — o compilador garante tudo.

Qual é a mágica? O compilador verifica o tipo e, se for compatível, “expõe” a variável do tipo necessário. Caso contrário, o bloco simplesmente não é executado.

Como isso fica em código real

Object obj = "Olá, Java 16+!";

if (obj instanceof String s) {
    System.out.println("Maiúsculas: " + s.toUpperCase());
} else {
    System.out.println("Não é uma string!");
}

3. Segurança e legibilidade: por que isso é ótimo

Elimina o erro ClassCastException

Object obj = 123;
// String s = (String) obj; // Bum! Exceção.

Com pattern matching, a variável é criada somente quando a verificação de tipo tem sucesso — o “casting errado” simplesmente não existe.

O código fica mais curto e mais claro
Duas linhas viram uma. Menos código “ruidoso” — mais fácil de ler e manter.

Exemplo: tratamento de tipos diferentes

public static void printInfo(Object obj) {
    if (obj instanceof String s) {
        System.out.println("String com tamanho " + s.length());
    } else if (obj instanceof Integer i) {
        System.out.println("Número inteiro: " + (i + 1));
    } else {
        System.out.println("Tipo desconhecido: " + obj);
    }
}

4. Exemplos de uso e nuances

Verificação de vários tipos

Object value = ...;

if (value instanceof String s) {
    System.out.println("É uma string: " + s);
} else if (value instanceof Number n) {
    System.out.println("É um número: " + n);
} else {
    System.out.println("Outra coisa: " + value);
}

Uso com null
Se o objeto for null, instanceof sempre retornará false — não haverá NPE, mas o bloco não será executado.

Object obj = null;

if (obj instanceof String s) {
    // Este bloco NUNCA será executado se obj == null
    System.out.println("String: " + s);
} else {
    System.out.println("obj — é null ou não é string");
}

Pattern matching com herança

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

Animal a = new Dog();

if (a instanceof Dog d) {
    d.bark(); // Podemos chamar métodos de Dog sem casting!
}

Lembre-se: a ordem das verificações é importante. Vá do mais específico ao mais genérico, caso contrário as verificações “estreitas” podem não ser alcançadas.

Comparação: abordagem antiga e nova

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

5. Restrições do pattern matching para instanceof

  • Escopo da variável. A variável do padrão é visível apenas no ramo em que a verificação é verdadeira.
if (obj instanceof String s) {
    System.out.println(s); // s está disponível
}
// System.out.println(s); // Erro! s não é visível aqui
  • Não é possível declarar várias variáveis de tipos diferentes em uma única condição.
// Erro de compilação:
if (obj instanceof String s || obj instanceof Integer i) {
    // ...
}
  • Requer Java 16+. Em versões mais antigas do JDK a nova sintaxe não é suportada.

6. Exemplos práticos (com base em um aplicativo simples)

Vamos imaginar um Gerenciador de Tarefas simples com diferentes tipos de tarefas.

Classes

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;
    }
}

Processamento com pattern matching

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

7. Nuances úteis

Tabela: pattern matching para instanceof — prós e contras

Prós Contras/Restrições
Menos código, mais legibilidade Requer Java 16+
Sem risco de ClassCastException Variável visível apenas dentro do bloco if
Segurança de tipos no nível do compilador Não funciona para vários tipos em uma única condição
Prático para lidar com herança Pode não ser suportado em IDEs e builds antigos
Serve para quaisquer classes

Esquema visual: como funciona o pattern matching para instanceof

+---------------------------+
|      Object obj           |
+---------------------------+
            |
            v
  if (obj instanceof Type t)
            |
      Sim           Não
   (true)        (false)
    |               |
    v               v
 t disponível     t não existe
   (código)         (sem acesso)

8. Erros típicos ao usar pattern matching para instanceof

Erro nº 1: tentar usar a variável fora do bloco if. Você declarou a variável no padrão; saiu do bloco — a variável não existe mais. O compilador reclama, com razão: “Quem é s?”

Erro nº 2: esperar que instanceof funcione com null. Se o objeto for null, a condição instanceof é sempre falsa, a variável não é criada. Trate null separadamente, se necessário.

Erro nº 3: usar a nova sintaxe em uma versão antiga do JDK/IDE. No Java 11 e anteriores, o pattern matching para instanceof não está disponível — você receberá um erro de sintaxe. Verifique a versão do JDK.

Erro nº 4: confusão com escopo. A variável do padrão está disponível somente no ramo em que a verificação é verdadeira. Fora dele — ela não existe.

Erro nº 5: esperar suporte a vários tipos ao mesmo tempo. Não é possível declarar duas variáveis de tipos diferentes em uma única condição: if (obj instanceof String s || obj instanceof Integer i) — isso não é permitido. Para cada tipo, sua própria verificação.

1
Tarefa
JAVA 25 SELF, nível 65, lição 1
Bloqueado
Analizador inteligente de dados 🔍
Analizador inteligente de dados 🔍
1
Tarefa
JAVA 25 SELF, nível 65, lição 1
Bloqueado
Identificação de animais no abrigo 🐾
Identificação de animais no abrigo 🐾
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION