Más Reflexión

Reflection es un API de Java que es muy útil y que es utilizada por muchos frameworks de Java, como Spring, Struts o Trapestry, ya que permite acceder a métodos, atributos y ver el comportamiento de una clase durante la ejecución del programa.

Reflection puede servir para crear entornos de desarrollo visuales, herramientas que sirvan para realizar pruebas a algún componente, herramientas de depuramiento (aka debugging) o algún marco de trabajo que cree instancias e inyecte propiedades de objetos a partir de un archivo de configuración

Así que está vez muestro una clase que realizó un compañero de trabajo ya hace algunos años y que permite crear instancias y/o acceder a las propiedades (a tráves de los métodos accesores) de manera reflexiva. Esta es una herramienta muy útil ya que permite obtener propiedades de objetos de manera que podemos usarla para ordenar beans de manera mas general sin tener que definir un comparator para cada bean dependiendo de la propiedad que se desee comparar, convertir una lista de un beans en un mapa o crear listas de con alguna de las propiedades del bean.


/*
* GenericBean.java
*
* Created on 22 de junio de 2006, 09:32 PM
*

*/

/**
*
* @author JM
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class GenericBean {
private Object o;
private Class beanClass;

/** Creates a new instance of GenericBean */
public GenericBean(String className) {
try {
beanClass = Class.forName(className);
Constructor c = beanClass.getConstructor();
o = c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}

public GenericBean(Object instance) {
o = instance;
beanClass = o.getClass();
}

public Object get(String property) {
Object ret = null;
property = property.substring(0, 1).toUpperCase()
+ property.substring(1);
try {
String methodName = "get" + property;
Method method = beanClass.getMethod(methodName);
ret = method.invoke(o);
}
catch(Exception e) {
try {
String methodName = "is" + property;
Method method = beanClass.getMethod(methodName);
ret = method.invoke(o);
}
catch(Exception ex) {
e.printStackTrace();
}
}

return ret;
}

public void set(String property, Object value) {
property = property.substring(0, 1).toUpperCase()
+ property.substring(1);
try {
Method method = beanClass.getMethod("set" + property, value
.getClass());
method.invoke(o, value);
} catch (Exception e) {
e.printStackTrace();
}
}

public Object getObject() {
return o;
}

public Class getObjectClass() {
return o.getClass();
}
}

Mañana escribiré como poder usar esta clase, porque la verdad ahorita ya es un poco noche jeje y ya me estoy quedando dormido. Sólo como recordatorio adicional, es importante recordad que utilizar Reflection genera bajas en el performance la máquina virtual ya que muchas veces no es posible utilizar los optimizadores con los que cuenta la JVM, como pueden ser en multiples llamadas a métodos, recursiones de cola etc...

Saludos
Gus

Anotaciones en Java

Nivel: Intermedio

Las anotaciones en Java, son marcas que se hacen a una parte del programa, que no tienen un efecto directo sobre el mismo pero que son reflexivas en la ejecución, es decir, pueden ser utilizadas por algún contenedor al momento de la ejecución del programa.


Las anotaciones son un tipo especial de modificador y puede ser usando junto a otros modificadores, tales como public, static, private etc... Digamos que las anotaciones son una forma de implementar una interfaz, sin que la clase lo haga directamente. Por ejemplo, creas un clase Perro, y entonces la anotas para decir que es un Animal, de está manera, en la ejecución del programa y utilizando reflexión es posible saber que cualquier objeto de clase Perro es un animal. Es decir estamos indicando que Perro es un animal y cumple una función similar a una interfaz.


@Animal
public class Perro {
//Algún buen metodo de la clase perro
}




Definir una anotación es algo muy sencillo, se hace de igual forma que una interfaz y se antepone una "@" al inicio de la palabra interface, y los métodos que contenga serán los elementos de la anotación, y sólo pueden regresar tipos primitivos, String y Enums.





public @interface Animal {
boolean vertebrado();
}


Con la anotación presentada anteriormente, podremos anotar alguna clase y definir si el Animal que estamos anotando es vertebrado o invertebrado


@Animal( vertebrado = true )
public class Perro {

}



De está forma en la ejecución del Programa podemos saber si que un objeto de clase Perro es un animal, y que tipo de animal es, además podemos especificar que la anotación solo sirve para anotar clases, ya que no podemos tener métodos de tipo animal. Y para hacer esto anotamos nuestra anotación. Entonces nuestra anotación queda así:


package anotaciones;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;



@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Animal {

boolean vertebrado();

}



De esa forma específicamos que la anotación sólo sirve para definir tipos. Ahora cómo usarlo en la ejecución:




package anotaciones;

import java.util.ArrayList;
import java.util.List;

public class Main {

@SuppressWarnings("unchecked")
public static void main(String[] args) {

//Creamos una Lista
List obj = new ArrayList();

//Agregamos 2 Perros
obj.add(new Perro());
obj.add(new Perro());

//Agregamos 1 String
obj.add("Soy un String");

System.out.println("Numero de animales en la lista:" + contarAnimales(obj));
}


public static int contarAnimales(List o ) {
if(o==null)
return 0;
else {
System.out.println("Empezando a contar");
int count = 0;
for (Object object : o) {
//System.out.println(object.getClass().getAnnotation(Animal.class));
if(object.getClass().isAnnotationPresent(Animal.class)) {
count++;
}
}
return count;
}
}

}



Aunque el ejemplo no es de lo más ortodoxo, da una muestra de lo que pueden hacer las anotaciones, y de como que es las utilizan los frameworks como JAXB o Spring 2.5 Anotado, en el cual se puede hacer el Autoalambrado, definir controlador, mapeos de request con anotaciones evitando tener que configurar un dispatcher servlet muy grande.

Saludos