Anotaciones en Java

Las anotaciones o decoradores sobre el código se han vuelto muy comunes en los últimos tiempos. Permiten al programador añadir información útil extra ya sea para comentar mejor el código o para modificar la forma de compilar/ejecutar una clase concreta. Son una extensión a Java para permitir la programación orientada a aspectos.

Las anotaciones pueden ser de tres tipos, según el momento en el que son visibles:

Información para el Compilador

Estas anotaciones permiten al compilador indicar si debe o no omitir errores y warnings o qué hacer con ellos. A nada que se haya trabajado con un IDE Java (como eclipse) se habrán utilizado este tipo de anotaciones de forma natural, por ejemplo usando @Override sobre una función para indicar que está sobreescribiendo una declaración definida en una clase padre. Esta anotación es completamente opcional,  pero permite tanto al compilador como al desarrollador comprobar que efectivamente se está sobreescribiendo una funcionalidad existente por herencia.

Por ejemplo:

public class Padre {     
    public void do(){
        System.out.println("Padre");
     }
}

public class Hijo extends Padre{     
    @Override
    public void do(){
        System.out.println("Hijo");
     }
}
Anotaciones en Tiempo de Compilación y Despliegue

Estas anotaciones permiten añadir información extra al compilador para que modifique la forma en la que se genera el código de los ficheros .class. Puede servir para modificar clases (añadiendo o modificando funcionalidad respecto a lo descrito en el código fuente), generar clases nuevas (por ejemplo en base a un fichero descriptor), etc…

Estas anotaciones sólo serán visibles en este punto, es decir, no se escribirán sobre los .class y por tanto no se podrán consultar en tiempo de ejecución.

Anotaciones en Tiempo de Ejecución

Estas anotaciones pueden ser consultadas en tiempo de ejecución y funcionan de forma muy parecida a como se utilizaría una interfaz.

Veamos directamente un ejemplo de cómo crear una anotación Runtime y cómo se puede utilizar. La anotación MyAnnotation se podrá aplicar a elementos de tipo field, es decir, a atributos de una clase:

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
     public @interface MyAnnotation {
}

Ahora podemos crear una clase que esté anotada con esta anotación:

public class myObject
 {
 @MyAnnotation
 public String field;
 }

De esta forma, en cualquier otra parte del código, podemos comprobar mediante reflexión si un objeto tiene un campo marcado con la anotación:

Class<?> res = objeto.getClass();
for (Field f : res.getFields()) {
     if (f.isAnnotationPresent(MyAnnotation.class)) {
          System.out.println("OK");
      }
}

Más información:

The annotations on the code or decorators have become very common. They allow the programmer to add additional useful information about how to improve the code or change how to compile / run a particular class. They are a Java extension to allow aspect-oriented programming.

There are three types of annotations, according to the moment when they are used:

Information for the Compiler

These annotations allow the compiler to indicate whether or not to ignore errors and warnings or what to do with them. If you’ve worked with a Java IDE (like eclipse) probably you would have used this type of annotations, for example using @Override on a function to indicate that you are overwriting a method defined on a parent class. This annotation is completely optional, but allows both the compiler and the developer to check that they are indeed overwriting existing hierarchical functionality.

For example:

public class Parent {     
    public void do(){
        System.out.println("Parent");
     }
}

public class Son extends Parent{     
    @Override
    public void do(){
        System.out.println("Son");
     }
}
Compiler-time and deployment-time processing

These annotations allow the compiler to add extra information about how to generate the code. It can serve to modify classes (adding or modifying functionality from those described in the source code), create new classes (based on a file descriptor), etc …

These annotations will only be visible at this point, they are not written on the .class files and therefore they cannot be available at runtime.

Runtime Annotations

This annotations can be used on runtime and they work on a very similar way as an interface.

Let’s see an example on how to create a Runtime Annotation and how can we use it. The annotation named MyAnnotation can be applied to elements oftype field:

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
     public @interface MyAnnotation {
}

Now we can create an annotated class by this annotation:

public class myObject
 {
 @MyAnnotation
 public String field;
 }

This way, we can check by reflection if an object has an annotated field on any part of the code:

Class<?> res = objeto.getClass();
for (Field f : res.getFields()) {
     if (f.isAnnotationPresent(MyAnnotation.class)) {
          System.out.println("OK");
      }
}

More Information: