Entendendo Java Reflection em 2 minutos
Introdução A Java Reflection é uma poderosa API que permite a um programa Java examinar e manipular informações sobre suas próprias classes em tempo de execução. Com a Reflection, é possível obter informações sobre campos, métodos e construtores de uma classe, além de acessar e modificar esses elementos mesmo que eles sejam privados. Neste post vamos escrever alguns códigos Java explorando algumas das facilidades de se usar Reflection e quando aplicar em seus projetos. Classe Bank Criaremos uma simples classe chamada Bank , onde iremos criar alguns campos, métodos e construtores para que sejam explorados pelo uso do Reflection. Acessando os campos da classe Bank Com a classe Bank criada, vamos explorar via Reflection a listagem de todos campos da classe através do método getDeclaredFields da classe Class . Perceba que através do método estático Class.forName , passamos como parâmetro uma string com o nome da classe em que desejamos explorar via Reflection. Saída Field name: code Field type: class java.lang.Integer ************ Field name: nameOfBank Field type: class java.lang.String ************ Field name: amountOfDepositedMoney Field type: class java.lang.Double ************ Field name: totalOfCustomers Field type: class java.lang.Integer ************ Acessando os métodos da classe Bank Através do método getDeclaredMethods , podemos recuperar todos os métodos da classe Bank. Saída Method name: doDeposit Method type: class java.lang.String ************ Method name: doWithDraw Method type: class java.lang.String ************ Method name: getReceipt Method type: class java.lang.String ************ Criando objetos Com o uso do Reflection para criar objetos, é necessário cria-los através de um construtor. Neste caso, devemos primeiro invocar um construtor para que seja criado o objeto. O detalhe é que para recuperar este construtor, devemos nos atentar aos tipos dos parâmetros que compõem o construtor e a ordem que eles são declarados. Isso torna flexível recuperar diferentes construtores com quantidade de parâmetros e tipos diferentes. Perceba abaixo que foi necessário criar um array do tipo Class atribuindo diferentes tipos de acordo com a composição do construtor que iremos usar para criar o nosso objeto. Neste cenário, será necessário invocar o método class.getConstructor( argType ) passando o array criado anteriormente como argumento. Dessa forma, teremos um objeto construtor que será usado na criação do nosso objeto. Por fim, criamos um novo array do tipo Object atribuindo os valores que irão compor o nosso objeto obedecendo a ordem definida no construtor e em seguida, basta invocar o método constructor.newInstance(argumentsValue) passando o array como parâmetro retornando o objeto em que desejamos criar. Saída Bank{code=1, nameOfBank='Bank of America', amountOfDepositedMoney=1.5, totalOfCustomers=2500} Invocando métodos Para invocar um método através de Reflection é bem simples como é mostrado no código abaixo. Perceba que é necessário passar como parâmetro no método cls.getMethod("doDeposit", argumentsType) o nome explícito do método, no caso o "doDeposit" e no segundo parâmetro, um array representando o tipo do dado usado no parâmetro do método doDeposit( double amount ) , no caso um parâmetro do tipo double . Por fim, invocar o método method.invoke passando como primeiro parâmetro o objeto referenciando a classe, no caso um objeto do tipo Bank. E como segundo parâmetro, o próprio valor do parâmetro que será executado no método. Saída 145.85 of money has been deposited Conclusão O uso de Reflection é uma boa estratégia quando necessita-se de flexibilidade em explorar diferentes classes e seus métodos sem a necessidade de instanciar objetos. Normalmente usa-se Reflection em componentes específicos de uma arquitetura mas não impede de ser usado em cenários variados. Pelo exemplos mostrados acima, percebe-se cenários infinitos de sua aplicação e as vantagens do seu uso. Espero que tenha curtido!