Conceito de Reflexão
O mecanismo de reflexão permite a inspeção e manipulação dinâmica de classes, métodos e atributos em tempo de execução no Java. Isso possibilita descobrir a estrutura de qualquer classe ou invocar métodos de objetos de forma genérica.
Funcionalidades da Reflexão
- Identificar a classe de um objeto em tempo de execução
- Criar instâncias de classes dinamicamente
- Consultar métodos e atributos de uma classe
- Invocar métodos de objetos via código genérico
- Gerar proxies dinâmicos
Classes e Interfaces de Exemplo
interface Legivel {
void leitura();
}
class Produto implements Legivel {
private String codigo;
private String descricao;
public double preco;
public Produto() {}
public Produto(String codigo) {
this.codigo = codigo;
}
public Produto(String codigo, String descricao) {
this.codigo = codigo;
this.descricao = descricao;
}
public String getCodigo() { return codigo; }
public void setCodigo(String codigo) { this.codigo = codigo; }
public String getDescricao() { return descricao; }
public void setDescricao(String descricao) { this.descricao = descricao; }
public double getPreco() { return preco; }
public void setPreco(double preco) { this.preco = preco; }
public static void atualizar() {}
@Override
public void leitura() {}
}
Obtendo uma Classe
Existem três formas principais de obter o objeto Class:
// Método 1: Class.forName
Class> classeA = Class.forName("Produto");
// Método 2: Atributo .class
Class> classeB = Produto.class;
// Método 3: getClass()
Produto item = new Produto();
Class> classeC = item.getClass();
Recuperando Atributos
Use getDeclaredFields() para obter todos os atributos declarados na classe, incluindo privados. getFields() retorna apenas os públicos.
Class> classe = Class.forName("Produto");
Field[] campos = classe.getDeclaredFields();
for (Field campo : campos) {
System.out.println(campo);
}
Recuperando Métodos
getMethods() lista todos os métodos públicos, incluindo herdados de Object.
Class> classe = Class.forName("Produto");
Method[] metodos = classe.getMethods();
for (Method metodo : metodos) {
System.out.println(metodo);
}
Recuperando Interfaces e Superclase
Class> classe = Class.forName("Produto");
Class>[] interfaces = classe.getInterfaces();
Class> superclasse = classe.getSuperclass();
Recuperando Construtores
Class> classe = Class.forName("Produto");
Constructor>[] construtores = classe.getConstructors();
for (Constructor> construtor : construtores) {
System.out.println(construtor);
}
Exemplo Prático 1: Criando uma Instância e Chamando Métodos
Class> classe = Class.forName("Produto");
Object obj = classe.newInstance();
Produto prod = (Produto) obj;
prod.setCodigo("X100");
prod.setDescricao("Widget");
System.out.println("Código: " + prod.getCodigo() + ", Descrição: " + prod.getDescricao());
Exemplo Prático 2: Modificando Atributos Privados
Class> classe = Class.forName("Produto");
Object obj = classe.newInstance();
Field codigoField = classe.getDeclaredField("codigo");
codigoField.setAccessible(true); // Permite acesso a campos privados
codigoField.set(obj, "Y200");
System.out.println(codigoField.get(obj));
Exemplo Prático 3: Operações Combinadas
Class> classe = Class.forName("Produto");
Object obj = classe.newInstance();
Field codigoField = classe.getDeclaredField("codigo");
codigoField.setAccessible(true);
codigoField.set(obj, "Z300");
Method setDescricao = classe.getDeclaredMethod("setDescricao", String.class);
setDescricao.setAccessible(true);
setDescricao.invoke(obj, "Componente");
Field descField = classe.getDeclaredField("descricao");
descField.setAccessible(true);
String descricao = (String) descField.get(obj);
System.out.println("Descrição: " + descricao);
Method getDescricao = classe.getDeclaredMethod("getDescricao");
getDescricao.setAccessible(true);
String descRetorno = (String) getDescricao.invoke(obj);
System.out.println("Método getDescricao: " + descRetorno);
Exemplo Prático 4: Métodos e Atributos Estáticos
Considere a classe Utilitario:
class Utilitario {
public static String nome = "padrao";
public static void mostrarMensagem() { System.out.println("Mensagem estática"); }
public static String obterDica() { return "Dica"; }
public static void processar(String texto) { System.out.println("Processando: " + texto); }
public static String calcular(int valor) { return "Resultado: " + valor; }
}
Exemplo de uso:
Class> classe = Class.forName("Utilitario");
Field nomeField = classe.getDeclaredField("nome");
String valorNome = (String) nomeField.get(null); // Acesso a atributo estático
System.out.println(valorNome);
Method mostrar = classe.getDeclaredMethod("mostrarMensagem");
mostrar.invoke(null);
Method obter = classe.getDeclaredMethod("obterDica");
String dica = (String) obter.invoke(null);
System.out.println("Dica: " + dica);
Method processar = classe.getDeclaredMethod("processar", String.class);
processar.invoke(null, "teste");
Method calcular = classe.getDeclaredMethod("calcular", int.class);
String resultado = (String) calcular.invoke(null, 5);
System.out.println(resultado);
Criando Instâncias com Construtores Específicos
Class> classe = Class.forName("Produto");
// Construtor sem parâmetros
Object obj1 = classe.newInstance();
// Construtor com um parâmetro
Constructor> constr1 = classe.getDeclaredConstructor(String.class);
Object obj2 = constr1.newInstance("A123");
// Construtor com dois parâmetros
Constructor> constr2 = classe.getDeclaredConstructor(String.class, String.class);
Object obj3 = constr2.newInstance("B456", "Peça");
Resumo das APIs de Reflexão
Para construtores:
getConstructor(Class<?>...)– Retorna um construtor público específico.getConstructors()– Retorna todos os construtores públicos.getDeclaredConstructor(Class<?>...)– Retorna um construtor específico, independentemente do modificador.getDeclaredConstructors()– Retorna todos os construtores da classe.
Para métodos:
getMethod(String, Class<?>...)– Retorna um método público específico.getMethods()– Retorna todos os métodos públicos.getDeclaredMethod(String, Class<?>...)– Retorna um método específico.getDeclaredMethods()– Retorna todos os métodos declarados.
Para atributos:
getField(String)– Retorna um atributo público específico.getFields()– Retorna todos os atributos públicos.getDeclaredField(String)– Retorna um atributo específico.getDeclaredFields()– Retorna todos os atributos declarados.