Cuando salió Java 5 el código se lleno de anotaciones. Para los que no las ubiquen son esas sentencias que comienzan con una @ y que se colocan antes de la declaración de una clase o de un atributo o de un método:
import org.junit.After; import org.junit.Before; import org.junit.Test; @Deprecated public class AlgunaClaseTest { @Before public void setUp() { } @Test public void testAlgo() { } @After public void tearDown() { } }
Al principio me disgustaban ya que a mi gusto ensuciaban el código y rompian con las reglas de sintaxis basicas de Java (the simpler the better), pero pasado de un tiempo es posible por fin tenerles agrado después de ver todas sus ventajas.
Una anotación se define asi en el código:
public @interface Anotacion {
}
O asi en caso de que quisieramos parametros:
public @interface AnotacionParametro {
String parametro();
}
public @interface AnotacionParametros {
int id();
String valor();
}
Las anotaciones pasadas se podrian usar de este modo en una clase
@Anotacion public class AlgunaClase { // Cuando es un solo parametro se puede omitir el nombre y el '=' @AnotacionParametro("parametro") public void algunMetodo() { } @AnotacionParametros(id=1, valor="algo") public void algunOtroMetodo() { } }
Es importante al ver el código el no confundir a la a anotación con una interface tradicional, las anotaciones no se heredan ni forman parte del diseño de clases de los sistemas, estas unicamente sirven para agregarle metadatos al miembro sobre el cual se colocan. Se podria decir que son 'comentarios avanzados'.
El ponerle anotaciones al código no cambiaria ABSOLUTAMENTE NADA en el comportamiento del mismo. La pregunta es entonces: Si no cambia nada, ¿Para qué las quiero?
Ejemplo
Supongamos que queremos crear un programa que permita correr clases tipo pruebas unitarias y que queremos que solamente se ejecuten los métodos que esten definidos como pruebas:
public class TestCase { @Test public void prueba() { } @Test public void excepcion() { throw new RuntimeException("Error aqui"); } @Test public void otraPrueba() { } @Test public void otraExcepcion() { throw new RuntimeException("Otro error aqui"); } }
Para esto previamente tendríamos que haber definido una anotación llamada Test, la cual deberia de ser importada por todas las clases que se quisieran probar. Nuestra anotación debe de tener definida otra anotación para que funcione del modo que queremos (sí, las anotaciones pueden tener anotaciones :) ), esta es @Retention y tiene como atributo la política de retención RetentionPolicy.RUNTIME para que el compilador la mantenga ahi después de haber creado el archivo class, ya que por default son eliminadas al compilar el archivo. Otra anotación que es conveniente indicar es @Target(ElementType.METHOD) para evitar que sea colocada en otro elemento que no sea un método. Estas anotaciones y enumeraciones estan todas en el paquete java.lang.annotation
import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Test { }
Y ahora si, nuestro Test Runner quedaria del siguiente modo:
import java.lang.reflect.*;
public class TestRunner {
public static void main(String[] args) throws Exception {
int exito = 0;
int fallas = 0;
Class clazz = Class.forName(args[0]);
Object obj = clazz.newInstance();
for (Method m : clazz.getMethods()) {
if (m.isAnnotationPresent(Test.class)) {
try {
m.invoke(obj);
System.out.printf("Prueba %s ejecutado%n", m.getName());
exito++;
} catch (Throwable t) {
System.out.printf("Prueba %s fallo: %s %n", m, t.getCause());
fallas++;
}
}
}
System.out.printf("OK: %d, Fallas: %d%n", exito, fallas);
}
}
El código es muy sencillo, unicamente crea un objeto usando la clase pasada como primer argumento en la línea de comandos y ejecuta todos los métodos que tengan una anotación del tipo Test.class definida, hace un conteo de errores y finalmente muestra el resumen.
Conclusión
Muchos de los frameworks actuales utilizan reflection muchísimo (Spring, JUnit, Hibernate, JSF, etc, etc, etc...), la implementación de anotaciones desde Java 5 ha permitido que algunos de estos se mantengan alejados del comportamiento del código del sistema y unicamente utilicen los metadatos para llevar a cabo sus tareas, favoreciendo asi la limpieza y legibilidad del código.
Es importante que aunque sea rara la vez que tengamos que programar una nueva anotación, sepamos emplearlas correctamente y sacarles provecho para tener sistemas mas limpios y menos acoplados.
Links
Aqui se puede encontrar la referencia oficial de Sun (in english of course) sobre anotaciones, el ejemplo se tomo de aqui y fue mejorado en este post ;) - http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
Publica tutoriales de Action Script donde manejes leyes físicas!!!; como cae un hombre de un edificio y su velocidad aumenta y que tan lejos salpica la sangre por la fuerza con la que se estrella su cabeza, cosas asi.
ResponderBorrarSaludos Chiquita.
-A
Chale, blog ñoño con comentarios de ñoños que no entienden lo que leen (lo digo por el alex no por mi)
ResponderBorrarGracias por el post. Es claro y explica bien los conceptos.
ResponderBorrarExcelente publicación, para nosotros los que no teníamos ni idea de como codificar anotaciones en Java y que a partir de este momento ya logramos este código, así que gracias por compartir el conocimiento. Atte: Alfonso.
ResponderBorrarasí que esas eran las recientemente populares anotaciones! n_n ... gracias por compartir tu conocimiento ;)
ResponderBorrarPara Alex: ve a aprender html creo que se te hará mas fácil, deja a JAVA para personas con un poquito mas de IQ.
ResponderBorrarPD: Excelente explicacion, llevo 6 paginas webs y esta es la unica q me lo ha explicado bien xD
Muy buen post. Gracias Víctor Hugo!
ResponderBorrarBuen post, bien explicado. Gracias.
ResponderBorrar