El presente artículo es una introducción a la reflexión en Java. Esta técnica permite “destripar” las clases de Java, obteniendo la información de su estructura a bajo nivel. ¿Qué ventajas tiene ésto?. La verdad es que muchas, ilustremos con un ejemplo.
Imaginemos el desarrollo de un servidor de aplicaciones que está basado en servicios. Cada servicio es atendido por una clase especializada, dependiendo de un tipo de mensaje.
Si queremos ejecutar un servicio específico que atienda una solicitud determinada, lo normal es hacer un anidamiento de sentencias IF para que instancie y ejecute cada clase según el caso. Esto tiende a complicar el desarrollo, hace ilegible el código, no es óptimo, y para integrar este servidor de aplicaciones en otros proyectos, habrá que borrar IF’s y crear otros para las clases de servicio que correspondan.
Pero si utilizamos la reflexión, este anidamiento de IF’s desaparece, dejando lugar a una única instanciación dinámica, que puede ser recogida de una base de datos o de un archivo. ¿Suena bien, verdad?
Para simplificar este caso, se ha realizado una simulación con clases básicas.
Lo primero es definir una interfaz, la cual servirá para definir la estructura de las clases que harán de servicio, creando los métodos por los cuales se invocan.
public interface IInterface
{
public int operacion(int a, int b);
}
Una vez definida la interfaz, se crean las clases servicio basadas en dicha interfaz:
Clase A
public class A implements IInterface
{
private int s1, s2;
public A()
{
s1 = 0;
s2 = 0;
}
public A(int a, int b)
{
s1 = a;
s2 = b;
}
public int operacion(int a, int b)
{
return a+b;
}
}
Clase B
public class B implements IInterface
{
public int operacion (int a, int b)
{
return a-b;
}
}
Para obtener un objeto a partir de una clase, de la cual no se conoce el nombre, se utiliza el siguiente código:
String clase = "A"; Class c = Class.forName(clase);
A partir de ahora, el objeto “c” contendrá la información referida a dicho objeto. A partir de aquí se podrá saber si es una clase, una interfaz, si es pública, privada, protegida, sincronizada, abstracta, etc. Se podrá acceder a todos sus constructores, métodos, parámetros, etc. (mirar código de ejemplo más abajo).
Lo realmente importante para nuestro ejemplo, es poder instanciar dicha clase y ejecutar sus métodos. Para ello se crea la instancia mediante la interfaz, que define el tipo de clase, y a través del objeto obtenido anteriormente:
String clase = "A";
Class c = Class.forName(clase);
// Instanciacion dinamica
IInterface objeto = (IInterface) c.newInstance();
System.out.println("Resultado: " + objeto.operacion(3, 2));
Como se puede apreciar, ya no estamos limitados por los nombres de las clases escritos estáticamente en el código, si no que podemos obtenerlos de un archivo o de una tabla de base de datos, e ir instanciando dinámicamente.
