Metaprogramação – API Reflection
da linguagem Java
Paulo Eduardo Papotti
Prof. Dr. Antonio Francisco do Prado
Metraprogramação
“Metaprogramação é a programação de programas que
escrevem ou manipulam outros programas (ou a si
próprios) assim como seus dados.”
Vantagens
→ Maior produtividade
→ Menos código
Desvatagens
→ Maior cuidado na hora de programar
→ Nem todas as linguagens oferecem esse recurso
Metaclasse
“Em orientação a objetos, uma metaclasse é uma classe
cujas instâncias também são classes e não objetos no
sentido tradicional. Assim como classes definem o
comportamento de certos objetos, metaclasses definem o
comportamento de certas classes e suas instâncias.”
Em Java:
Class classe = Aluno.class;
Fatorial em tempo de compilação
#include <iostream>
using namespace std;
template <int N> // Esta é a definição do template
struct Fatorial {
static const int valor = N * Fatorial<N - 1>::valor;
};
template <> // Esta é a definição do caso base
struct Fatorial<0> {
static const int valor = 1;
};
int main (int argc, char *argv[]) {
cout << Fatorial<5>::valor << endl;
cout << Fatorial<2>::valor << endl;
return 0;
}
Java Reflection API
Java manipulando Java

Uma das capacidades incomuns do Java é que um
programa pode analisar a si próprio.

É possível descobrir:


A classe de um objeto

Modificadores de acesso, superclasse, campos, construtores e métodos.

Se a classe implementa uma interface.
É possível fazer:

Criar instancia da classe

Obter e modificar a variaveis de instância.

Invocar um método de uma classe.
Para que serve Reflection?

Em programas comuns não é necessário usar
Reflection.

Usa-se Reflection se o seu programa necessita
processar o próprio programa ou outros
programas.

Exemplos típicos:
» Um navegador de classes
» Um depurador
» Um construtor de GUI
» Uma IDE, tal como Netbeans ou Eclipse
A classe Class

Para obter informações sobre uma classe, é necessário seu
objeto Class.
» Se você tem um objeto obj, você pode obter seu objeto
classe através:
Class c = obj.getClass();
» Você pode obter a classe da superclasse de uma Class c
através:
Class sup = c.getSuperclass();
» Se você souber o nome da classe em tempo de compilação,
você pode obter seu objeto classe através:
Class c = Aluno.class;
» Se você souber o nome da classe em tempo de execução
em uma String str, o objeto classe pode ser obtido através:
Class c = class.forName(str);
Obetndo o nome da classe



Se você tem uma classe de objeto c, pode-se obter
o nome da classe com o comando c.getName()
getName retorna o nome completo da classe
(incluindo pacotes),
Class c = Button.class;
String s = c.getName();
System.out.println(s);
irá exibir:
java.awt.Button
A classe Class e seus métodos estão em java.lang,
que é um pacote de classes que sempre é
importado para qualquer programa Java.
Obtendo os modificadores de um objeto Class

Os modificadores (public, final, abstract etc.) de
um objeto Class podem ser acessados através do
método getModifiers().

Um modifier é na verdade um int mas a classe
Modifier possui métodos para definir qual é o tipo
do modificador. Por exemplo:
if (Modifier.isPublic(m))
System.out.println("public");
Obtendo os modificadores de um
objeto Class

Modifier contém esses métodos (entre outros):
»
»
»
»
»
»
»
public static boolean isAbstract(int)
public static boolean isFinal(int)
public static boolean isInterface(int)
public static boolean isPrivate(int)
public static boolean isProtected(int)
public static boolean isPublic(int)
public static String toString(int)
Obtendo interfaces


Para saber quais interfaces um objeto Class implementa
basta chamar o método getInterfaces(), que retorna um
array de objetos Class.
Ex:
static void printInterfaceNames(Object o) {
Class c = o.getClass();
Class[] allInterfaces = c.getInterfaces();
for (Class inf: allInterfaces) {
System.out.println(inf.getName());
}
}
Examinando classes e interfaces



A classe Class representa tanto classes quanto
interfaces
Para determinar se um objeto c do tipo Class é
uma interface, use-sa c.isInterface()
Métodos úteis de um objeto Class são:
»
»
»
»
»
getModifiers()
getFields()
getConstructors()
getMethods()
isArray()
Obtendo Fields

public Field[] getFields() throws SecurityException
» Retorna um array de Field (somente atributos públicos
incluindo atributos herdados).
» O tamanho do array pode ser zero
» Não existe uma ordem definida para retornar os atributos,
mas, em geral, eles vem na ordem que foram declarados
» pulic Field getField(String name)
throws NoSuchFieldException, SecurityException
» Retorna o objeto Field de um determinado atributo (apenas
público)
» Para acessar atributos privados também, usa-se o método
public Field[] getDeclaredFields() e pulic Field
getDeclaredField(String name)
Usando Fields

Se f é um objeto Field então
»
»
»
»
f.getName() retorna o nome simples do atributo
f.getType() retorna o tipo (Class) do atributo
f.getModifiers() retorna os Modifiers do atributo
f.toString() retorna uma String contendo
modificadores de acesso, o tipo, e o nome
completo do atributo
» Example: public java.lang.String Person.name
Usando Fields

Os atributos de um objeto obj podem ser
acessador através:
» boolean f.getBoolean(obj), int f.getInt(obj),
double f.getDouble(obj), etc., retornam o valor do
atributo desde que seja do tipo correto (tipos
primitivos)
» Object f.get(obj) retorna o atributo (objetos)
» void f.set(obj, value), void f.setBoolean(obj,
bool), void f.setInt(obj, i), void f.getDouble(obj,
d), etc. seta o valor do atributo;
Obtendo Construtores de uma
classe
Se c é um objeto Class, então
 c.getConstructors() : Constructor[] retorna um array de
todos os construtores públicos de uma da classe c.
 c.getConstructor( Class … paramTypes ) retorna um
construtor que possua os mesmos parâmetros dados por
paramTypes.
Ex:
 String.class.getConstructors().length
> 15; // A classe String possui 15 construtores públicos
 String.class.getConstrucor( char[].class, int.class,
int.class).toString()
> String(char[], int,int).

Construtores

Se c é um objeto Constructor, então
» c.getName() retorna o nome do construtor em uma
String (é o mesmo nome da classe)
» c.getDeclaringClass() retorna a Class no qual o
construtor foi declarado
» c.getModifiers() retorna os Modifier do construtor
» c.getParameterTypes() retorna um array de objetos
Class na ordem que foram declarados
» c.newInstance(Object… initargs) cria e retorna um
nova instância da classe c
Exemplo

Constructor c = String.class.getConstrucor(
char[].class, int.class, int.class).toString()

String(char[], int,int).
String s = c.newInstance(
new char[] {‘a’,’b’,’c’,’d’ }, 1, 2 );

s = “bc”;
A classe Method

public Method[] getMethods()
throws SecurityException
Retorna um array de objetos Method (apenas métodos
públicos de uma classe ou interface, incluindo
métodos herdados)
Não há ordem específicas que os métodos são
retornados
public Method getMethod(String name,
Class… parameterTypes)
throws NoSuchMethodException, SecurityException
Methods
getDeclaringClass()
→ Retorna o objeto Class representando a classe ou interface
que declarou o método

getName()
→ Retorna o nome do método em uma String

getModifiers()
→ Retorna os modificadores do método em formato int.

getParameterTypes()
→ Retorna um array de objetos Class que representam os
tipos dos parâmetros do método em questão.

Methods
getReturnType()
→ Retorna o objeto Class que representa o tipo de retorno do
método

toString()
→ Retorna uma String que descreve o método

public Object invoke(Object obj, Object… args)
→ Invoca o método, de um determinado objeto com
parâmetros especificados.

Examplos de invoke()
“abcdefg”.length()
>> 7
 Method lengthMethod = String.class.getMethod(“length”) ;
 lengthMethod.invoke(“abcdefg”)
>> 7
 “abcdefg”.substring(2, 5)
>> cde
 Method substringMethod = String.class.getMethod (
“substring”, int.class, Integer.TYPE ) ;
 substringEMthod.invoke( “abcdefg”, 2, new Integer(5) )
> > cde

Obtendo membros não públicos de uma
classe





Todos as chamadas getXXX() métodos da classe Class
mencionados retorna apenas membros public da classe
alvo.
Para obter também membros privados, protegidos,
estático existem chamadas do tipo getDeclaredXXX()
getDeclaredConstructors(),
getDeclaredConstrucor(Class…)
getDeclaredFields(),
getDeclaredField(String)
getDeclaredmethods(),
getDeclaredMethod(String, Class…)
Mais informações

Documentação
http://download.oracle.com/javase/7/docs/technotes/guides/lang/index.html

Exemplos de códigos
http://java.sun.com/developer/codesamples/refl.html
Download

Java Reflection