Jugando con Reflection
Uno de los mejores inventos del siglo pasado es sin dudas la API Reflection de Java, extrañamente me veo rodeado a menudo de gente que, o bien no la conoce, o bien le da miedo. A los primeros solo puedo darles el consejo de que lean el capitulo 9 del libro Hardcore Java para que se enteren de que va, a los segundos solo puedo darles la razón…La API Reflection es como un martillo, lo podemos usar para construir una iglesia o para romperle la cabeza a alguien, despues no sirve para nada. Así, usar esta API permite que nuestros programas interactuen con clases de las cuales no conoce absolutamente nada (nos podemos olvidar de implementar interfaces!) ó bien podemos hacer un “bypass” de los modificadores de acceso haciendo inservible a cualquier objeto. Dominar la API Reflection para no caer en las incontables tentaciones que nos ofrece es una disciplina de autocontrol digna de un arte marcial.
Para los que no se avisparon todavia de que va la API Reflection la idea es basicamente manipular “metainformación” de las clases en tiempo de ejecucion para poder conocer los metodos, propiedades ó constructores de clases que quiza ni sabiamos que existian. A continuacion dejo un pedazo de codigo que muestra las virtudes, a veces peligrosas, de esta API.
public class Perro {
private void ladrar() {
System.out.println(“GUAU!”); //un metodo privado para ladrar.
}
}public class PruebaReflection {
public static void main(String[] args) {
Perro p = new Perro(); //Nada del otro Mundo.
Class clase = p.getClass(); //A no confundir Class con class. El
// metodo getClass() devuelve un objeto
//de clase Class con la “metadata” de la
// clase Perro :SMethod metodo = clase.getDeclaredMethod(“ladrar”) //Method es a los
//metodos lo que Class
// es a las clasesmetodo.setAccesible(true) //wow.. le decimos que ignore los
// modificadores de acceso del metodo.
metodo.invoke(p); //el metodo invoke de la clase Method permite
// invocar a un metodo sobre un objeto en
//particular, en este caso sobre nuestro Perro p.
}
}
Si ejecutamos el codigo aparecera en la pantalla GUAU! que a priori no podriamos haber accedido por ser privado de la clase Perro ¿Aterrador verdad?. En el otro extremo imaginense la tarea de armar la GUI de un CRUD (create, read, update, delete…) para nuestro modelo. No es negocio hacer a mano una ventana para cada clase que participa en nuestro modelo, en cambio podemos aprovechar la API Reflection para que en tiempo de ejecucion arme dinamicamente las ventanas de acuerdo a las propiedades que encuentre en las clases que les indicamos. ¿Nos ahorraria bastante tiempo, no?