viernes, 4 de diciembre de 2009

Java Reflection

En un momento se me dio la necesidad de invocar los métodos getter y setter de una clase dinámicamente, y al googlear me encontré con la API de reflection de Java junto al ejemplo que aparece en esta página

Con esto logre invocar los métodos getter y setter sin necesidad de invocarlos explícitamente ( instancia.getValor ), para lo cual hice el siguiente ejemplo.


primero una clase donde tenemos el origen de los datos



PersonaOrigen.java


public class PersonaOrigen {

private String nombre;
private String apellido;
private String edad;

public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getApellido() {
return apellido;
}
public void setApellido(String apellido) {
this.apellido = apellido;
}
public String getEdad() {
return edad;
}
public void setEdad(String edad) {
this.edad = edad;
}


}




una clase donde volvaremos los datos.


Persona.java


public class Persona {

private String nombre;
private String apellido;
private String edad;

public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getApellido() {
return apellido;
}
public void setApellido(String apellido) {
this.apellido = apellido;
}
public String getEdad() {
return edad;
}
public void setEdad(String edad) {
this.edad = edad;
}


}



Y tenemos la clase que realiza la operacion.


Prueba.java
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;





public class Prueba {





public static void main(String[] args) {



/*

* La clase PersonaOrigen Representara la fuente de los datos

*/

PersonaOrigen po = new PersonaOrigen();

po.setNombre("Juan");

po.setApellido("Perez");

po.setEdad("18");



/*

* por simplicidad, en este caso supondremos que los

* campos que vienen de la fuente de datos son conocidos

* por lo cual los guardaremos en un ArrayList

* (Cuando lo implemente los obtenia de base de datos)

*/

ArrayList<String> campos = new ArrayList<String>();

campos.add("nombre");

campos.add("apellido");

campos.add("edad");





HashMap metodos;

try{

metodos = new HashMap();

Persona persona = new Persona();

        Field[] fields = persona.getClass().getDeclaredFields();



        /*

         * recorro la clase y almaceno los atributos en un hashmap

         * esto se podria evitar, y grabar directamente los datos.

         */

        for( int zz = 0;  zz < fields.length ; zz++ ){

            metodos.put(fields[zz].getName(), fields[zz]);

        }

        

        //recorremos los campos

        Iterator i = campos.iterator();

        String nombreCampo = null;

        while(i.hasNext()){

        

         //rescato el nombre del campo

         nombreCampo = (String) i.next();

        

         //genero el string que contiene el nombre de los metodos getter y settet de cada campo

String setterName = "set" + String.valueOf(nombreCampo.charAt(0)).toUpperCase() + nombreCampo.substring(1);

String getterName = "get" + String.valueOf(nombreCampo.charAt(0)).toUpperCase() + nombreCampo.substring(1);



//rescato el valor de la fuente de origen de los datos

                Method getter = po.getClass().getMethod(getterName);

                Object valor = getter.invoke(po, new Object[0]);



                //seteo el valor en la instancia de la clase Persona

Field field2= (Field) metodos.get(nombreCampo);

Method setter = persona.getClass().getMethod(setterName, field2.getType());

setter.invoke(persona, new Object[]{( valor ) });         

        

        }



        /*

         * Finalmente podemos ver volcados los datos de PersonaOrigen a persona

         */

        System.out.println("Nombre:" + persona.getNombre());

        System.out.println("Nombre:" + persona.getApellido());

        System.out.println("Nombre:" + persona.getEdad());

        



}

catch (Exception e) {

;

}





}



}