Reflection JAVA
Por Thiago Almeida
(thiago2010.2@gmail.com)

Olhar para sí própria como em um espelho, examinando sua estrutura e propriedades é um artifício importante. Essa é Reflection a introspecção das classes JAVA.



Reflection é um pacote JAVA que permite criar chamadas de métodos e conhecer a estrutura de um programa em tempo de execução, sem precisar conhecer as classes envolvidas quando estamos escrevendo nosso código. Essa facilidade se torna importante quando é necessário resolver determinadas tarefas que só notamos ao receber dados, em tempo de execução.

Imagine uma situação onde você tem uma lista de objetos genérica e a forma de ordenação

dessa lista pode mudar dependendo do objeto que está sendo usado em tempo de execução.

Note que, como não conhecemos os objetos da lista, não poderemos criar comparadores

em tempo de compilação. Para resolver esse problema usando Java Reflection, ao criar uma

lista que armazena determinado tipo de objetos, recuperamos os atributos da classe que

representa esse tipo, podendo então criar um comparador a nossa vontade.

No exemplo abaixo, vamos conhecer alguns métodos da api Java Reflection e como

eles podem ser usados. Para isso, definimos uma classe Pessoa, a classe Reflection

que fará toda manipulação sobre objetos do tipo Pessoa e a classe Main que executará

uma aplicação simples. A partir desse exemplo, queremos mostrar que podemos obter

qualquer informação, executar métodos e obter valores de uma classe sem precisar

conhecer, de fato, a classe envolvida.

O Reflection, na prática usa as classes do pacode java.lang.reflect.

Exemplo:

Descrição da classe Pessoa

package logica;
public class Pessoa {
        private String nome;
        private int idade;
        private String cpf;
        private String rg;
        
        public Pessoa(String nome, int idade, String cpf, String rg){
                this.nome = nome;
                this.idade = idade;
                this.cpf = cpf;
                this.rg = rg;
        }
        public String getNome() {
                return nome;
        }
        public int getIdade() {
                return idade;
        }
        public String getCpf() {
                return cpf;
        }
        public String getRg() {
                return rg;
                }
}
Descrição da classe Reflection
package logica;
import java.lang.reflect.*;
public class Reflection {
        
        public Reflection() {
        }
        
        public void listaNomeDosMetodos(){
                try {
                        Class cl = Class.forName("logica.Pessoa");
                        Method[] metodos = cl.getDeclaredMethods();
                        
                        for(int i = 0;i< metodos.length;i++){
                                System.out.println(metodos[i].toString());
                        }
                        
                } catch (Throwable e) {
                        System.err.print(e);
                }
        }
        public void atributos(){
                try{
                        Class cl = Class.forName("logica.Pessoa");
                        Method metodos[] = cl.getDeclaredMethods();
                        for(int i = 0;i< metodos.length;i++){
                                Method m = metodos[i];
                                System.out.println("Nome do metodo: "+m.getName());
                                System.out.println("Parametros:");
                        
                                for(int z = 0;z< m.getParameterTypes().length;z++){
                                        System.out.println("        "+z+": "+m.getParameterTypes()[z]);
                                }
                                
                                System.out.println("Tipo de returno: "+m.getReturnType());
                        }
                        
                }catch(Throwable e){
                        System.err.print(e);
                }
        }
        public void invocaMetodos(){
                Pessoa pessoa = new Pessoa("Thiago Almeida", 22, "cpf-Ficticio", "rg-Ficticio");
                try{
                        
                        Class cl = Class.forName("logica.Pessoa");
                        Field[] fi = cl.getDeclaredFields();
                        Method[] met = cl.getDeclaredMethods(); 
                        for(int g = 0;g< met.length;g++){
                                System.out.println(fi[g].getName()+": "+met[g].invoke(pessoa));
                        }
                        
                }catch(Throwable e){
                        System.err.print(e);
                }
        }
        
        
}
Descrição da classe Main
package apresentacao;
import logica.Reflection;
public class Main {
        public static void main(String[] args) {
                
                Reflection re = new Reflection();
                
                System.out.println("\n--- Lista todos os metodos da classe pesquisada ---\n");
                re.listaNomeDosMetodos();
                System.out.println("\n--- Lista atributos da classe ---\n");
                re.atributos();
                System.out.println("\n--- Invoca metodos da classe Pessoa ---\n");                
                re.invocaMetodos();
        }
}
As classes Pessoa e Main são simples e tem valor de formulação da aplicação. Vamos tentar entender a Classe Reflection. No primeiro método dessa calsse, "listaNomeDosMetodos()", listamos todos os métodos de uma classe qualquer passada como parâmetro. Note que, na linha 12, a classe é "capturada" apenas passando seu nome e armazenada em uma variável do tipo Class. Depois da classe armazenada na variável, capturamos os métodos declarados na classe através do método "getDeclaredMethods()".Nele é retornado um array com todos os métodos da classe Pessoa. O método "atributos()", inicialmente, faz o mesmo que "getDeclaredMethods()". Mas, agora, para cada método ainda podemos pegar o nome do métdo, os parâmetros de entrada, as variáveis internas ao método e o seu retorno. Fazemos isso para a classe Pessoa. O interessante é que, em momento algum, até agora, criamos uma instância da classe Pessoa. Por último, vamos entender o método "invocaMetodos()". Para ele, criamos uma instância de Pessoa para ser chamada depois. O método "getDeclaredFields()" pega todas as variáveis declaradas na classe Pessoa. Depois, para cada método de Pessoa, invocamos ele através do método "invoke()", esse método tem como funcionalidade invocar o método em questão da classe que foi passada como parâmetro. Na classe Main, apenas chamamos os métodos declarados na classe Reflection e observamos o resultado:
Nome do metodo: getNome
Parametros:
Tipo de returno: class java.lang.String
Nome do metodo: getIdade
Parametros:
Tipo de returno: int
Nome do metodo: getCpf
Parametros:
Tipo de returno: class java.lang.String
Nome do metodo: getRg
Parametros:
Tipo de returno: class java.lang.String
--- Invoca metodos da classe Pessoa ---
nome: Thiago Almeida
idade: 22
cpf: cpf-Ficticio
rg: rg-Ficticio
Hoje, criamos uma aplicação simples que descreve o uso de Java Reflection para que está iniciando nesse assunto. A aplicação usada para a construção dessa matéria pode ser encontrada aqui. Sugiro como exercício, baixar essa aplicação e tentar fazer a introspecção, agora, nas classes Notebook e Desktop e ver qual será a saída. FONTES: http://www.devmedia.com.br/java-reflection-parte-i/4888 http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/reflection-e-annotations/ http://pt.wikipedia.org/wiki/Reflex%C3%A3o_(programa%C3%A7%C3%A3o) http://docs.oracle.com/javase/tutorial/reflect/index.htm
Jornal PETNews - Edição: Jéssika Renally - Revisão: Tiaraju Smaneoto e Lívia Maria
Grupo PET Computação UFCG, 2012. All rights reserved.