O Operador instanceof
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 31 de 87.
A lição anterior mostrou que o downcasting pode falhar com uma ClassCastException se o objeto não for realmente o tipo para o qual você está convertendo. O operador instanceof resolve isso permitindo que você verifique o tipo de um objeto antes da conversão.
A sintaxe é direta: object instanceof ClassName retorna true se o objeto for uma instância dessa classe (ou de qualquer uma de suas subclasses):
Animal animal = new Dog();
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark(); // Seguro para chamar métodos específicos de Dog
}Esta verificação evita erros de tempo de execução ao garantir que a conversão (cast) seja bem-sucedida. O operador também retorna true para tipos pai na hierarquia:
Dog dog = new Dog();
System.out.println(dog instanceof Dog); // true
System.out.println(dog instanceof Animal); // true
System.out.println(dog instanceof Object); // trueDesde o Java 16, você pode combinar a verificação e o cast em uma única etapa usando pattern matching:
if (animal instanceof Dog dog) {
dog.bark(); // 'dog' já está convertido e pronto para uso
}Esta sintaxe mais limpa elimina a linha de cast separada. Observe que instanceof retorna false quando testado contra null, então você não precisa de uma verificação de nulo separada.
Desafio
FácilVamos construir um sistema de inspeção de veículos que utiliza o operador instanceof para identificar e lidar com segurança com diferentes tipos de veículos. Você criará uma hierarquia de veículos e escreverá um código que verifica o tipo real de cada veículo antes de acessar seus recursos especializados.
Você organizará seu código em quatro arquivos:
Vehicle.java: Crie a classe base que todos os veículos compartilham. Todo veículo possui um campomodel(String). Inclua um construtor para inicializá-lo, um método gettergetModel()e um métodoinspect()que imprime:"Inspecting vehicle: " + modelCar.java: Crie uma classe que estende Vehicle. Carros têm um campo adicionalnumDoors(int). Usesuperpara a inicialização do pai. Adicione um métodocheckDoors()que imprime:getModel() + " has " + numDoors + " doors"Motorcycle.java: Crie outra classe que estende Vehicle. Motocicletas têm um campohasSidecar(boolean). Adicione um métodocheckSidecar()que imprimegetModel() + " has a sidecar"ougetModel() + " has no sidecar"dependendo do valor booleano.Main.java: Aqui é onde oinstanceofse torna essencial! Você receberá quatro entradas: um modelo de carro, número de portas, um modelo de motocicleta e se ela tem um sidecar (true/false).Crie um array de referências de
Vehiclecontendo um Car e uma Motorcycle. Em seguida, percorra o array e para cada veículo:- Chame o método base
inspect() - Use
instanceofpara verificar se é um Car - se for, faça o downcast com segurança e chamecheckDoors() - Use
instanceofpara verificar se é uma Motorcycle - se for, faça o downcast com segurança e chamecheckSidecar()
- Chame o método base
Você receberá quatro entradas: o modelo do carro (String), número de portas (int), modelo da motocicleta (String) e se tem sidecar (boolean).
Sua saída deve mostrar quatro linhas - para cada veículo, você verá sua mensagem de inspeção seguida por sua verificação específica de tipo. O operador instanceof garante que você só chame métodos de Car em objetos Car reais e métodos de Motorcycle em Motorcycles reais, evitando qualquer ClassCastException!
Folha de consulta
O operador instanceof verifica se um objeto é uma instância de uma classe específica antes de realizar o casting:
Animal animal = new Dog();
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark(); // Seguro para chamar métodos específicos de Dog
}O operador retorna true para a classe do objeto e todas as classes pai na hierarquia:
Dog dog = new Dog();
System.out.println(dog instanceof Dog); // true
System.out.println(dog instanceof Animal); // true
System.out.println(dog instanceof Object); // trueDesde o Java 16, o pattern matching combina a verificação e o cast em uma única etapa:
if (animal instanceof Dog dog) {
dog.bark(); // 'dog' já está com o cast feito e pronto para uso
}O operador instanceof retorna false quando testado contra null, eliminando a necessidade de verificações de nulo separadas.
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Ler as entradas
String carModel = scanner.nextLine();
int numDoors = Integer.parseInt(scanner.nextLine());
String motorcycleModel = scanner.nextLine();
boolean hasSidecar = Boolean.parseBoolean(scanner.nextLine());
// TODO: Criar um objeto Car com carModel e numDoors
// TODO: Criar um objeto Motorcycle com motorcycleModel e hasSidecar
// TODO: Criar um array de referências Vehicle contendo o Car e a Motorcycle
// TODO: Percorrer o array e para cada veículo:
// 1. Chamar o método inspect()
// 2. Usar instanceof para verificar se é um Car, então fazer o downcast e chamar checkDoors()
// 3. Usar instanceof para verificar se é uma Motorcycle, então fazer o downcast e chamar checkSidecar()
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Iterator