Percorrer os atributos de um POJO em Java [Reflection]

Recentemente tive uma atividade para percorrer os atributos de um POJO que eu desconhecia, retornando os seus atributos e valores.

Para simplificar a demonstração foi ocultado os imports, package, métodos gets/sets e o construtor da classe. Vejamos o exemplo:

public class Cliente { 
    private int id;
    private String nome;
    private Date dtNascimento;
    private Endereco endereco;
    private int telefone;
}

Reparem que a classe Cliente possui um atributo do tipo endereco.

public class Endereco {
    private int id;
    private String rua;
    private int numero;
    private String bairro;
}

A terceira classe criada com o método main, instância o objeto cliente e faz a chamada para o método imprimeAtributoseValoresPojo passando como parâmetro a instância da classe cliente.

public class Teste {
    public static void main(String[] args) {        
        
        Endereco endereco = new Endereco(1, "Avenida Brasil", 147, "Centro");
        Cliente cliente = new Cliente(1, "José da Silva", new Date(), endereco, 32557744);
        
        Utilitarios utilitarios = new Utilitarios();        
        utilitarios.imprimeAtributoseValoresPojo(cliente);  
    }
}

Após receber a instância da classe cliente é adicionado todos os campos em um array do tipo Field. E com um foreach é acessado o nome e o valor do atributo.

public class Utilitarios {
    
    public void imprimeAtributoseValoresPojo(Object object){
        Class<?> classe = object.getClass();      
        Field[] campos = classe.getDeclaredFields();        
        
        String nomeAtributo = "";
        Object valorAtributo = null;        
        for (Field campo : campos) {            
            try {               
                nomeAtributo = campo.getName();
                campo.setAccessible(true); //Necessário por conta do encapsulamento das variáveis (private)
                valorAtributo = campo.get(object);                              
            } catch (Exception e) {
                e.printStackTrace();
            }           
            System.out.println(nomeAtributo + ": " + valorAtributo);            
        }       
    }

Vejamos a saída no console:

id: 1
nome: José da Silva
dtNascimento: Thu Aug 25 21:05:17 BRT 2016
endereco: br.com.getAttributesPojo.model.Endereco@5c647e05
telefone: 32557744

Beleza fera!!! E onde estão os dados do objeto endereço? Por se tratar de um objeto complexo é retornado o endereço em memória. Nesse caso precisamos identificar o tipo do atributo, e a partir disto realizar o mesmo procedimento anterior. Vejamos:

public class Utilitarios {
    
    public void imprimeAtributoseValoresPojo(Object object){
        Class<?> classe = object.getClass();      
        Field[] campos = classe.getDeclaredFields();        
        
        String nomeAtributo = "";
        Object valorAtributo = null;    
        Object tipoAtributo = null;
        for (Field campo : campos) {            
            try {               
                nomeAtributo = campo.getName();
                campo.setAccessible(true); //Necessário por conta do encapsulamento (private)
                valorAtributo = campo.get(object);
                tipoAtributo = campo.getType(); //Obtendo o tipo do atributo
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            System.out.println(nomeAtributo + ": " + valorAtributo);
            
            //Código adicionado
            if (tipoAtributo.toString().contains("br.com.getAttributesPojo")){
                Class<?> classeFilha = (Class<?>) tipoAtributo;
                Field[] camposFilha = classeFilha.getDeclaredFields();
                String nomeAtributoFilha = "";
                Object valorAtributoFilha = null;
                for (Field campoFilha : camposFilha) {
                    try {
                        nomeAtributoFilha = campoFilha.getName();
                        campoFilha.setAccessible(true);
                        valorAtributoFilha = campoFilha.get(valorAtributo); //Nesse momento é passado o valor do objeto endereço                        
                    } catch (Exception e) {
                        e.printStackTrace();
                    }                   
                    System.out.println("(Filha) " + nomeAtributoFilha + ": " + valorAtributoFilha);                                     
                }               
            }                       
        }       
    }
}

Executando novamente o retorno é esse:

id: 1
nome: José da Silva
dtNascimento: Thu Aug 25 21:45:22 BRT 2016
endereco: br.com.getAttributesPojo.model.Endereco@5c647e05
(Filha) id: 1
(Filha) rua: Avenida Brasil
(Filha) numero: 147
(Filha) bairro: Centro
telefone: 32557744

A API de reflection em Java é poderosa e nos permite analisar e manipular várias informações de uma classe (atributos, métodos, construtores e etc). Tive um pouco de dificuldade para obter as informações do objeto endereço e por isso decidi escrever. Caso queiram conhecer a API um pouco melhor, sugiro a leitura desse post ou acessem a documentação.

Abraço 😀

4 comments

Deixe uma resposta