O que é a Reflexão (Reflection)?
A Reflexão Java ou simplesmente Reflection é uma API do Java destinada a permitir que o código Java obtenha em tempo de execução informações sobre classes, seus campos, métodos e construtores, permitindo a manipulação dinâmica de código. Desta forma é destinada primariamente para ser utilizada por ferramentas especiais tais como depuradores (debuggers), interpretadores ou inspetores de classes e objetos.
Esta API, java.lang.reflect, pode ser utilizada para:
Apesar disso não se recomenda seu uso quando os mecanismos usuais da linguagem são suficientes para efetuar as operações desejadas.
Através do pacote java.lang.reflect temos acesso as classes Field, Method e Constructor que possibilitam determinar respectivamente quais os campos, métodos e construtores através de um ou mais métodos. Segue um exemplo que permite obter informações sobre os campos, consutores e métodos declarados em uma classe, cujo nome é fornecido como argumento da aplicação:
// ClassInfo.java import java.lang.reflect.*; public class ClassInfo { public static void main(String args[]) { // Verifica se foi dado um argumento if (args.length==0) { System.out.println("Uso:\n\tClassInfo <pacote.NomeClasse>"); System.exit(1); } try { // Carrega classe dinamicamente Class classe = Class.forName(args[0]); // Obtêm enumeração dos campos declarados Field campos[] = classe.getDeclaredFields(); // Obtêm enumeração dos contrutores declarados Constructor construtores[] = classe.getDeclaredConstructors(); // Obtêm enumeração dos métodos declarados Method metodos[] = classe.getDeclaredMethods(); int i; // Exibe campos System.out.println("Campos:"); for (i=0; i<campos.length; i++) System.out.println(campos[i].toString()); // Exibe construtores System.out.println("Construtores:"); for (i=0; i<construtores.length; i++) System.out.println(construtores[i].toString()); // Exibe métodos System.out.println("Metodos:"); for (i=0; i<metodos.length; i++) System.out.println(metodos[i].toString()); } catch (ClassNotFoundException e) { System.out.println("Classe não encontrada: " + e); } } }
O resultado desta aplicação para a classe java.lang.Number pode ser visto abaixo:
>java ClassInfo java.lang.Number Campos: private static final long java.lang.Number.serialVersionUID Construtores: public java.lang.Number() Metodos: public abstract int java.lang.Number.intValue() public abstract long java.lang.Number.longValue() public abstract float java.lang.Number.floatValue() public abstract double java.lang.Number.doubleValue() public byte java.lang.Number.byteValue() public short java.lang.Number.shortValue()
Ainda utilizando características da API de reflexão, podemos determinar qual a hierarquia de uma classes, isto é, qual sua(s) superclasse(s):
// ClassFamily.java import java.util.*; public class ClassFamily { public static void main(String args[]) throws Exception { // Verifica se foi dado um argumento if (args.length==0) { System.out.println("Usage:\n\tClassFamily <pacote.NomeClasse>"); System.exit(1); } Class classe = null; // Carrega classe dinamicamente classe = Class.forName(args[0]); // Determina hierarquia até java.lang.Object Vector hierarquia = new Vector(10); do { hierarquia.addElement(classe); classe = classe.getSuperclass(); } while (classe != null); // Exibe hierarquia int i = hierarquia.size()-1; System.out.println((""+(Class)hierarquia.elementAt(i--)).substring(6)); StringBuffer espacos = new StringBuffer(" "); for (; i>=0; i--) { System.out.print(espacos+"|\n"+espacos+"+----"); System.out.println((""+(Class)hierarquia.elementAt(i)).substring(6)); espacos.append(" "); } } }
O resultado desta aplicação para a classe java.lang.Float pode ser visto abaixo:
>java ClassFamily java.lang.Float java.lang.Object | +----java.lang.Number | +----java.lang.Float