Hierarquia de Herança e Conversão de Tipos em Java
Em Java, a conversão de tipos para objetos segue regras diferentes das aplicadas a tipos primitivos, pois está diretamente ligada à hierarquia de classes.
Exemplo de hierarquia
public class Program {
public static void main(String[] args) {
Person tom = new Person("Tom");
tom.display();
Person sam = new Employee("Sam", "Oracle");
sam.display();
Person bob = new Client("Bob", "DeutscheBank", 3000);
bob.display();
}
}
// Classe que representa uma pessoa
class Person {
private String name;
public String getName() {
return name;
}
public Person(String name) {
this.name = name;
}
public void display() {
System.out.printf("Person %s%n", name);
}
}
// Funcionário de uma empresa
class Employee extends Person {
private String company;
public Employee(String name, String company) {
super(name);
this.company = company;
}
public String getCompany() {
return company;
}
@Override
public void display() {
System.out.printf("Employee %s works in %s%n", getName(), company);
}
}
// Cliente de um banco
class Client extends Person {
private int sum; // saldo da conta
private String bank;
public Client(String name, String bank, int sum) {
super(name);
this.bank = bank;
this.sum = sum;
}
@Override
public void display() {
System.out.printf("Client %s has account in %s%n", getName(), bank);
}
public String getBank() {
return bank;
}
public int getSum() {
return sum;
}
}Essa hierarquia pode ser representada como:
Object → Person → Employee | Client

Todas as classes em Java herdam implicitamente de Object, que fica no topo da hierarquia.
Upcasting (conversão ascendente)
Um objeto de uma subclasse também é um objeto da sua superclasse. Isso permite, por exemplo:
Object tom = new Person("Tom");
Object sam = new Employee("Sam", "Oracle");
Object kate = new Client("Kate", "DeutscheBank", 2000);
Person bob = new Client("Bob", "DeutscheBank", 3000);
Person alice = new Employee("Alice", "Google");O upcasting é a conversão do tipo mais específico (subclasse) para um tipo mais genérico (superclasse). Essa conversão é automática e segura.
Downcasting (conversão descendente)
A conversão inversa — de superclasse para subclasse — é chamada de downcasting.
Nem todo objeto do tipo Person é necessariamente um Employee ou Client.
Por isso, o downcasting precisa ser feito de forma explícita.
Object sam = new Employee("Sam", "Oracle");
// Conversão explícita de Object para Employee
Employee emp = (Employee) sam;
emp.display();
System.out.println(emp.getCompany());Essa conversão é válida porque sam realmente armazena um Employee.
Também é possível converter usando toda a cadeia de herança:
Object kate = new Client("Kate", "DeutscheBank", 2000);
((Person) kate).display();
Object sam = new Employee("Sam", "Oracle");
((Employee) sam).display();Erro de downcasting
O problema ocorre quando o objeto real não é do tipo esperado:
Object kate = new Client("Kate", "DeutscheBank", 2000);
// Compila, mas gera ClassCastException em tempo de execução
Employee emp = (Employee) kate;
emp.display();Nesse exemplo, kate é um Client.
Converter para Person ou Client funciona, mas para Employee resulta em erro de execução, pois kate não é um Employee.
Prevenindo erros com instanceof
Para evitar problemas, é possível verificar o tipo real do objeto antes da conversão:
Object kate = new Client("Kate", "DeutscheBank", 2000);
if (kate instanceof Employee) {
Employee employeeKate = (Employee) kate;
employeeKate.display();
} else {
System.out.println("Conversion is invalid");
}O operador instanceof retorna true se o objeto for de um tipo específico (ou de um subtipo).
No exemplo, kate instanceof Employee retorna false, enquanto kate instanceof Client retornaria true.
Pattern Matching com instanceof
É possível simplificar o código usando pattern matching com instanceof:
Object kate = new Client("Kate", "DeutscheBank", 2000);
if (kate instanceof Client clientKate) {
clientKate.display();
} else {
System.out.println("Conversion is invalid");
}Aqui, a expressão:
kate instanceof Client clientKateVerifica se kate é um Client.
Se for, cria automaticamente a variável clientKate já convertida, evitando um casting manual separado.
📝 Exercícios
Tarefa 1 — Identificar tipo real do objeto
Descrição:
Dada a hierarquia Person → Employee e Person → Client, explique o resultado da expressão:
Object obj = new Client("Ana", "Itau", 2000);
boolean result = obj instanceof Employee;Resposta
result será false, pois o objeto real é Client, não Employee.
instanceof verifica o tipo real do objeto, não apenas o tipo da variável.
Tarefa 2 — Diferença entre upcasting e downcasting
Descrição: Explique a principal diferença entre upcasting e downcasting em Java e qual deles é seguro sem verificação prévia.