reflexão marco antonio arquiteto de software novembro/2007
TRANSCRIPT
ReflexãoMarco AntonioArquiteto de SoftwareNovembro/2007
O que é• Reflexão é geralmente utilizado por programas que
precisam modificar o comportamento de uma aplicação em tempo de execução
• É um recurso avançado e deve ser usado apenas quando o desenvolvedor tem um grande conhecimento sobre os fundamentos da linguagem
• Por outro lado, reflexão é uma técnica poderosa que faz as aplicações executar operações que seriam impossíveis de outra maneira
• Uma aplicação pode usar recursos externos, criando objetos usando apenas o nome das classes
Limitações da reflexão• Reflexão é um recurso poderoso, mas não
pode ser usada de qualquer modo• Se você puder executar uma operação sem
reflexão é melhor evitá-la...
Overhead• Reflexão envolve tipos que são definidos
dinamicamente, dessa forma, Java não consegue fazer todas as otimizações de um código normal
• Operações com reflexão são sempre mais lentas que as operações normais
• Essas operações devem ser evitadas em código muito executado, por questões de performance
Segurança• Reflexão requer permissões especiais que
podem não estar disponíveis em ambientes seguros
Exposição• Reflexão permite que você execute código
privado, o que pode resultar em comportamento não esperado
• Código com reflexão acaba com sua abstração e pode ter comportamento diferente com a atualização da plataforma
Objetos dinâmicos• O ponto inicial para reflexão é
java.lang.Class• Todas as demais classes estão no pacote
java.lang.reflect
ClasseReflexivapackage net.javabasico.reflexao;
public class ClasseReflexiva {
public void executaUmMetodo() {
System.out.println("Executei um método");
}
}
TestaAReflexaopackage net.javabasico.testereflexao;
1. import java.lang.reflect.*;
public class TestaAReflexao { public static void main(String[] args) {2. try {3. Class clazz = Class.forName("net.javabasico.reflexao.ClasseReflexiva");4. Object objeto = clazz.newInstance();5. Method m = clazz.getMethod("executaUmMetodo");6. m.invoke(objeto);7. } catch (Exception e) {8. e.printStackTrace(); } } }
Recuperando um método1. Todas as classes que você vai usar estão
nesse pacote2. Para usar reflexão é necessário o try/catch
para tratamento das exceções geradasExemplo: você pode digitar o nome do método
errado, o Eclipse não vai poder te ajudar
3. Cria um objeto do tipo Class chamado clazz (o nome poderia ser qualquer um)Vamos recuperar os métodos desse objeto através da reflexão
Cont.4. Precisamos de um objeto do tipo Object
para executar (invocar) o nosso método de exemplo
5. Recupera o método baseando-se em seu nome através da reflexão
6. Executa (invoca) o método
7. Fecha o tratamento de exceção
8. Imprime os erros, caso ocorram
ClasseReflexivapackage net.javabasico.reflexao;
public class ClasseReflexiva {
public String umaString = "Esse é meu valor padrão";
public void executaUmMetodo() {
System.out.println("Executei um método");
}
}
TestaAReflexaopackage net.javabasico.testereflexao;
import java.lang.reflect.*;
public class TestaAReflexao { public static void main(String[] args) { try { Class clazz = Class.forName("net.javabasico.reflexao.ClasseReflexiva"); Object objeto = clazz.newInstance(); // Method m = clazz.getMethod("executaUmMetodo"); // m.invoke(objeto);1. Field atributo = clazz.getField("umaString");2. System.out.println(atributo.get(objeto)); } catch (Exception e) { e.printStackTrace(); } }}
Recuperando um atributo1. Recupera o atributo pelo nome
2. Recupera e imprime o valor do atributo
ClasseReflexivapackage net.javabasico.reflexao;
public class ClasseReflexiva { public String umaString = "Esse é meu valor padrão";
public void executaUmMetodo() { System.out.println("Executei um método"); } public void executaOutroMetodo(String parametro) { System.out.println("O parâmetro é: " + parametro); }}
TestaAReflexaopackage net.javabasico.testereflexao;
import java.lang.reflect.*;
public class TestaAReflexao { public static void main(String[] args) { try { Class clazz = Class.forName("net.javabasico.reflexao.ClasseReflexiva"); Object objeto = clazz.newInstance();1. Method m = clazz.getMethod("executaOutroMetodo", String.class);2. m.invoke(objeto, "Marco Antonio"); } catch (Exception e) { e.printStackTrace(); } }}
Método com parâmetro1. Recupera o método pelo nome, informando
qual o tipo do parâmetro. No nosso caso, o parâmetro é uma String
2. Invoca o método passando o valor. Esse valor será utilizado pelo objeto
ClasseReflexivapackage net.javabasico.reflexao;
public class ClasseReflexiva { public String umaString = "Esse é meu valor padrão";
public void executaUmMetodo() { System.out.println("Executei um método"); }
public void executaOutroMetodo(String parametro) { System.out.println("O parâmetro é: " + parametro); }
public String recuperaUmValor() { return "Esse valor foi recuperado"; }}
TestaAReflexaopackage net.javabasico.testereflexao;
import java.lang.reflect.*;
public class TestaAReflexao { public static void main(String[] args) { try { Class clazz = Class.forName("net.javabasico.reflexao.ClasseReflexiva"); Object objeto = clazz.newInstance();1. Method m = clazz.getMethod("recuperaUmValor");2. String s = (String) m.invoke(objeto);3. System.out.println(s); } catch (Exception e) { e.printStackTrace(); } }}
Recuperando um valor1. Recupera o método pelo nome
2. Invoca o método. O sublinhado é chamado de cast, ou seja, conversão, pois o método pode retornar uma String, um Double, ou qualquer outra classe java
3. Imprime o valor de retorno do método
Exercícios• Utilizando reflexão, execute todos os
métodos da classe ContaCorrente
Alguns métodos utilitáriospackage net.javabasico.testereflexao;
import java.lang.reflect.*;
public class TestaAReflexao { public static void main(String[] args) { try { Class clazz = Class.forName("net.javabasico.reflexao.ClasseReflexiva");1. System.out.println(clazz.getPackage());2. for (Method m : clazz.getMethods()) {3. System.out.println(m.getName()); }4. for (Field f : clazz.getFields()) { System.out.println(f.getName()); } } catch (Exception e) { e.printStackTrace(); } }}
Utilitários1. Imprime o pacote da classe
2. Estrutura conhecida como forEach (“para cada”)Exemplo: para cada método de clazz, faça algo,
no nosso caso, imprima
3. Imprime o nome de cada um dos métodos da classe
4. Imprime cada um dos atributos da classe
Dúvidas