Negocio

Reflexão em Java: Exemplos e Mecanismo

Reflexão

Java permite reflexão , ou seja, o código que você escreve para que possa visualizar e alterar o comportamento em tempo de execução. Pense nisso como um espelho. Você não vê aquela mancha na sua gravata até vê-la no espelho. O mesmo pode ser aplicado à reflexão. Java pode ver as informações sobre uma classe, embora possa não estar acessível quando o programa está em execução.

Antes de retirar o espelho, vamos construir uma pequena classe que podemos usar em nossos experimentos. O código a seguir configura uma classe para o chá verde, incluindo algumas variáveis ​​e métodos para obter e definir valores.

SELECT emp.empID, emp.empName 
FROM funcionário
 (SELECT planCode, COUNT (empID) como emp_count
  FROM benefícios
  GROUP BY plancode) subconsulta 1
WHERE subconsulta1.empID = funcionário.empID;
classe pública GreenTea { 
  cafeína dupla privada;
  Mistura de cordas privada;
  public double totalCaffeine;
  GreenTea público (código     interno ) {
   if (código == 25) {
blend = "Dragonwell"
    cafeína = 42,58;
   }
   if (código == 30) {
    blend = "Zen";
    cafeína = 29,5;
   }
  }
  public double getCaffeine () {
   return cafeína;
  }
  public String getClend () {
   return blend;
  }
  public void setCaffeine (double
   cafeine ) { this.caffeine = cafeína;
  }
  public String setBlend (String blend) {
   this.blend = blend;
  }
  public void calcValues ​​(double oz) {
   totalCaffeine = oz * cafeína;
   System.out.println ("Cafeína total =" + totalCaffeine);
  }
}

Há muito código aqui, mas usaremos reflexão para encontrar (e alterar) algumas dessas peças.

Obtenha o nome de uma classe

Antes que possamos fazer qualquer coisa com reflexão, precisaremos importar o utilitário Java principal que nos permite fazer isso. Os métodos de reflexão do Java estão no pacote java.lang.reflect. Para usá-los, colocamos a seguinte instrução de importação antes de qualquer classe que usará esses métodos:

import java.lang.reflect. *;

A primeira coisa que faremos é recuperar algumas informações sobre a classe GreenTea, tanto seu nome de objeto quanto o nome verdadeiro da classe.

// obtém o objeto de classe 
Class green = GreenTea.class;
System.out.println (verde);

Quando este código é executado, a seguinte saída é exibida:

Saída de nome de classe de reflexão Java

Temos mais uma opção que pode fazer mais sentido. Em vez de os nomes longos serem exibidos, também podemos obter o nome simples da classe. Então, que nome demos realmente a ele? O método de reflexão inclui o método getSimpleName:

// Nome simples 
String greenTeaSimple = green.getSimpleName ();
System.out.println ("Nome simples =" + greenTeaSimple);

Agora, a saída é muito mais limpa e nos dá um nome mais compreensível da classe:

Reflexão Java obtém saída simples

Obter Métodos

Podemos usar reflexão para obter os métodos de uma classe. Existe um método para obter métodos (como um comitê para revisar comitês!) Chamado getMethods (). Isso funciona, mas também retorna quaisquer métodos definidos pelo sistema em uma classe. Não precisamos necessariamente deles para esta lição. Em vez disso, podemos nos concentrar apenas nos métodos que realmente declaramos em nosso código. Lembre-se de que tínhamos três métodos: obter cafeína, obter misturas e definir o nível total de cafeína.

No código a seguir, usaremos o método getDeclaredMethods () para obter os métodos que definimos. O loop ‘for’ percorre os métodos e retorna o valor, usando o método getName ().

// obtém todos os métodos 
Method [] gtMethods = green.getDeclaredMethods ();
// faz um loop pelos métodos
de (método method: getMethods) {
  System.out.println ("Method =" + method.getName ());
}

Quando o código é executado, obtemos a seguinte saída:

Saída de métodos de obtenção de reflexão Java

Agora que temos os métodos, vamos tentar olhar os campos.

Obter campos

Essa é a parte que torna a reflexão um pouco perigosa. Lembre-se de que Java é ótimo em ocultar dados. Ele pode proteger as variáveis ​​como privadas, portanto protegidas de outros membros da classe. O Reflection permite quebrar essa barreira e acessar membros privados de uma classe. É por isso que você não atualizaria esses campos com reflexão.

Dito isso, vamos ver como podemos acessar os membros de uma classe. O código a seguir usa o método getDeclaredFields para retornar todos os campos em nossa classe GreenTea. Porque estamos usando reflexão, não importa que sejam particulares! Na verdade, você notará outra linha de código que destaca o motivo pelo qual não fazemos isso na produção ao vivo. É fácil contornar os métodos de proteção de dados do Java.

Classe verde = GreenTea.class; 
Field [] fields = green.getDeclaredFields ();
for (Field oneField: fields) {
  Field field = green.getDeclaredField ("blend");
  String gtFieldName = field.getName ();
  System.out.println ("Field =" + getFieldName);
// não faça isso na produção!
  field.setAccessible (true);
}

Observe como realmente alteramos o campo de privado para acessível. É por isso que devemos ter muito cuidado com a reflexão. É uma ótima ferramenta para recuperar a lista de métodos e campos de uma classe.

Instanciação de classe em movimento

Com reflexão, podemos até criar novas instâncias de classes instantaneamente! Esse tipo de codificação pode não ser para todos. Embora forneça algum código realmente dinâmico, pode ser difícil de implementar. Cobriremos um único exemplo, com base em nossa classe GreenTea, e percorreremos cada item do código.

Para instanciar uma nova instância de GreenTea, envie a ela um código 25 (lembra do parâmetro de código int que criamos no construtor da classe?). Em seguida, executaremos um dos métodos (calcValues) e enviaremos 23 onças. Observe que envolvemos as instruções em um bloco try e catch. Esses tipos de declarações podem ficar confusas rapidamente, portanto, estamos detectando quaisquer erros para que o programa não falhe completamente. Na verdade, você deve usar as instruções try e catch sempre que estiver tentando refletir.

tente { 
  GreenTea g = GreenTea.class.getConstructor (Integer.TYPE) .newInstance (25);
  g.calcValues ​​(23,25);
  // captura os erros
} catch (NoSuchMethodException e) {
  System.out.println ("Ei!");
}

A primeira linha é longa. Ele cria uma nova instância. Primeiro, ele precisa obter o construtor (getConstructor). Nosso construtor aceitou um valor Integer, então temos que dizer isso ao Java. Então temos que dizer a ele para criar uma nova instância E enviar junto com um valor int (neste caso 25). A próxima linha invoca o método e envia 23,25 (são as onças de chá).

Quando é executado, obtemos o seguinte resultado:

Reflexão Java cria saída de classe

Resumo da lição

A reflexão Java é usada para examinar (e até mesmo atualizar) a estrutura do programa em tempo de execução. Podemos recuperar nomes de classes, métodos e até membros privados de classes. A reflexão Java é ótima para testar, depurar e certificar-se de que nosso código está sendo executado da maneira que deveria. NÃO devemos usá-lo para manipular campos privados em um ambiente de produção ativo! Também podemos usar reflexão para criar novas instâncias de classes instantaneamente. Isso pode nos ajudar a entregar um código muito dinâmico.