W3docs

Operador instanceof do Java

Verifique o tipo em tempo de execução com o operador instanceof e use pattern matching para instanceof no Java.

instanceof faz uma pergunta em tempo de execução: "esta referência é realmente um T (ou um subtipo de T)?" A resposta é um boolean, e a forma moderna com pattern matching também vincula o valor a uma variável tipada em uma única etapa, eliminando a necessidade de um cast separado.

É a ferramenta que você usa sempre que tem uma referência polimórfica e precisa saber qual tipo concreto ela realmente é — tipicamente dentro de equals, ao percorrer uma estrutura de dados heterogênea, ou ao trabalhar com hierarquias seladas.

A forma básica

A sintaxe clássica é expression instanceof Type:

Object o = "hello";
if (o instanceof String) {
  String s = (String) o;
  System.out.println(s.length());
}

A verificação retorna true se o se refere a uma String ou qualquer subtipo, e false se o é null ou aponta para um tipo diferente de objeto. null instanceof Anything é sempre false — uma garantia pequena mas útil.

Pattern matching para instanceof

Desde o Java 16, instanceof aceita um type pattern que declara uma variável vinculada ao tipo reduzido na mesma expressão:

if (o instanceof String s) {
  System.out.println(s.length());   // no cast needed
}

Se a verificação for bem-sucedida, s está no escopo e já tipado como String. Se falhar, s não está no escopo. O cast desaparece, a redundância desaparece, e você não pode acidentalmente fazer cast de algo que a verificação rejeitou.

Escopo da variável vinculada

A variável vinculada está no escopo onde o compilador pode provar que a verificação foi bem-sucedida. Isso inclui o ramo do if, mas também flui através de && e para a negação do if:

if (o instanceof String s && s.length() > 3) { ... }   // s is in scope after && — also a String

if (!(o instanceof String s)) return;
System.out.println(s.length());   // s is in scope after the early return

Esse segundo padrão é especialmente útil para código no estilo de cláusula guarda — reduza o tipo, saia se não houver correspondência, e use o nome vinculado livremente abaixo.

O lado oposto é ||: o vínculo não flui através dele, porque o lado direito é executado precisamente quando a verificação falhou. o instanceof String s || s.length() > 0 não compila — s não está no escopo à direita do ||.

Restrições sobre o tipo alvo

O compilador rejeita verificações que ele pode provar serem impossíveis. "hello" instanceof Integer nem mesmo compila, porque String e Integer não são relacionados. Isso captura erros de digitação e resíduos de refatoração em tempo de compilação, e não em tempo de execução.

Ele também rejeita upcasts que não podem falhar: Object o = ...; if (o instanceof Object) {} é marcado como redundante.

Em switch

O mesmo mecanismo de pattern matching está disponível no switch, onde realmente brilha em hierarquias seladas:

String describe(Object o) {
  return switch (o) {
    case Integer i  -> "int " + i;
    case String  s  -> "str of length " + s.length();
    case int[]   a  -> "array of " + a.length;
    case null       -> "nothing";
    default         -> "something else";
  };
}

Com um tipo selado como seletor, você pode remover o default e o compilador exigirá um caso para cada subtipo permitido — combine isso com sealed classes para obter análise de casos exaustiva.

Quando usar — e quando não usar

Use instanceof quando o tipo é genuinamente desconhecido e a resposta muda o comportamento: implementando equals, processando hierarquias seladas de tagged-union, percorrendo nós de AST. Não o use como substituto para polimorfismo adequado — uma cadeia de if (x instanceof A) ... else if (x instanceof B) ... sobre uma hierarquia aberta é geralmente um sinal de que um método virtual no tipo faria o trabalho melhor.

Um exemplo prático

java— editable, runs on the server

O que vem a seguir

instanceof é um dos vários métodos aos quais todo objeto Java responde. O próximo capítulo amplia a visão para examinar o conjunto completo — java.lang.Object, a classe raiz que todo tipo estende silenciosamente, e os métodos que você herda dela independentemente de querer ou não. Continue para Java Object class.

Prática

Prática
O que o pattern matching para `instanceof` (`if (o instanceof String s)`) economiza em comparação com a forma clássica?
O que o pattern matching para `instanceof` (`if (o instanceof String s)`) economiza em comparação com a forma clássica?
Was this page helpful?