miércoles, 23 de octubre de 2013

Anotaciones en Java (Una notita para ayudarme)


Java es un lenguaje muy maduro y se ha dado a conocer por ofrecer posibilidades que otros lenguajes un poco más complejos no ofrecen, y una de las cosas que me han parecido más interesantes es la posibilidad de usar anotaciones para añadir meta-datos a un código fuente y que estos estén disponibles en tiempo de ejecución. Mediante esta herramienta es posible dejar en algunos casos de lado el uso de XML.


Okay, pero ¿Qué es una anotación?
Una anotación es una linea de código que se pone atrás de la sentencia, el método, la clase, el campo, el parámetro o el paquete al que se le quieren agregar los meta-datos, esta inicia con un carácter arroba (@) seguida de una interfaz para anotación y finalmente los parámetros de la anotación, mediante los cuales se asignan los meta-datos. Esto se ve así:

package test;

@SuppressWarnings("deprecation")
public class MiClase{

    @InicializadorDeArreglo(longitud=20,valorInicial="Hola")
    String miArreglo;

    @Override
    public void toString(){
        return "MiClase...";
    }
}

Como podemos ver en el ejemplo anterior hay dos anotaciones, una para la clase y otra para método, la primera (Linea 3) remueve las alertas generadas por código obsoleto, la segunda es una anotación creada como ejemplo y la tercera (Linea 9) se usa para especificar que un método no es propio de la clase actual, y que esta siendo reescrito (sobrecargado).

¿Y como creó mis propias anotaciones?
Una anotación no es más que una interfaz, pero tiene algo extra que permite que sea usada como anotación. veamos un ejemplo:
package test;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InicializadorDeArreglo{
    int longitud();
    Object valorInicial() default null;
}

Como vemos en el ejemplo una anotación se crea de la misma manera que una interfaz, pero se usa la palabra reservada @interfaz. Además se pueden usar valores por defecto para los atributos mediante la palabra reservada default. Una de las cosas que se deben tener en cuenta a la hora de hacer una anotación es para que tipo de campos se debe poder usar, en este caso la anotación solo sera usada para atributos de clase, por eso se pone como target ElementType.FIELD. La sentencia @Retention(RetentionPolicy.RUNTIME) determina cuanto tiempo deben estar disponibles los datos de la anotación, para el caso RetentionPolicy.RUNTIME la anotación estará disponible a lo largo de toda la ejecución de la aplicación.

Muy bien, pero ¿Cómo accedo a los meta-datos?
Para aceder a los meta-datos es necesario usar Java Reflection, a continuación veremos un metodo que usa Reflection para inicializar los atributos con la anotación @InicializadorDeArreglo:

package test;


public class Inicializador{

    public static void inicializar(Object obj){
        Field[] f = obj.getClass().getDeclaredFields();
        for (Field a : f) {
            InicializadorDeArreglo i = a.getAnnotation(
                             InicializadorDeArreglo.class);
            if (i != null) {
                a.setAccessible(true);
                try {
                    String []array = new String[i.longitud()];
                    for(int it=0; it<i.longitud(); it++)
                        array[it] = i.valorInicial();
                    a.set(obj, array);
                } catch (Exception e) {
                    System.err.println("Error: " + e.getMessage());
                }
            }
        }
    }

}

Como vemos en el ejemplo lo que se hace es tomar mediante Java Reflection los atributos de la clase y filtrar aquellos que tengan un tipo especifico de anotación (lineas 9, 10 y 11), para este caso la clase de la anotación es InicializadorDeArreglo. Luego creamos el valor que sera asignado al atributo (linea 14), después se asigna el valor por defecto a cada celda del arreglo (lineas 15 y 16 ) y finalmente se asigna el valor (17). El proceso de asignación se ejecuta adentro de un try-catch para que si el tipo del atributo de destino es diferente de el valor a asignar no se detenga toda la aplicación.

Espero que les sea útil, si les ha gustado compartan y comentes, hasta una próxima publicación.