En 2005, con la llegada de Java 5, conocimos nuevas entidades llamadas anotaciones.

Las anotaciones son una forma especial de metadatos sintácticos que se pueden declarar en el código. Se utilizan para analizar el código en la compilación o en tiempo de ejecución. Puede pensar en una anotación como una etiqueta, una etiqueta o una sugerencia del compilador.

Probablemente te hayas encontrado con anotaciones antes. Por ejemplo, al anular un método de la clase principal, escribimos @Override antes del método en sí. Esta anotación indica que el método principal se anulará en la clase secundaria.

Sintaxis:


@Override
public int hashCode() {
      return super.hashCode();
}

Quiero señalar de inmediato que las anotaciones no solo se aplican a los métodos. Se utilizan con paquetes, clases, métodos, campos y parámetros.

Para entender cómo funcionan las anotaciones, primero vamos a familiarizarnos con el concepto de una interfaz de marcador. Desde la llegada de Java, los desarrolladores siempre han necesitado una forma de marcar clases para realizar ciertas acciones en ellas.

Antes de Java 5, usaban una interfaz que no hacía lo que esperamos que hagan las interfaces. No tenía métodos ni contrato. Simplemente marcó una clase como especial de alguna manera.

Tal interfaz se denominó interfaz de marcador. Por el nombre, puede adivinar que su propósito es marcar clases para la JVM, el compilador o alguna biblioteca. Quedan algunas interfaces de marcador, como Serializable . Esta interfaz de marcador nos permite indicar que las instancias de una clase se pueden serializar.

Como hemos visto, las interfaces de marcador continúan vivas incluso después de la introducción de las anotaciones.

Anotaciones versus interfaces de marcador:


@MyAnnotation
public class MyClass {}

public class MyClass implements MarkerInterface {}

Ambos enfoques tienen el mismo objetivo, pero existe una clara diferencia en su implementación. Por ejemplo, considere una interfaz y una anotación que indique que una clase pertenece a un tipo particular.

Si estamos usando una interfaz, entonces marcamos la clase. Si lo usamos incorrectamente y ocurre un error, entonces descubriremos el problema en la compilación y el programa no se ejecutará.

Con las anotaciones, no todo es tan simple: aquí el error se detectará en tiempo de ejecución, lo que significa que el programa se iniciará, pero, como era de esperar, no terminará.

Tenga en cuenta que si necesitamos marcar una clase para uso futuro, sus instancias deben pasarse a un método específico:


public class MyInteger implements Sum {}
interface Sum {};

public static void main(String[] args) throws IOException {
        increase(new MyInteger());
}
 
public static void increase(Sum count) {
        // TODO
}

Una interfaz de marcador funciona mejor aquí.

Es mejor usar anotaciones cuando necesitamos algo más, como los parámetros que admiten las anotaciones.

Veamos las anotaciones estándar en el JDK:

Anotación Descripción Ejemplo
@Override Especifica que un método anula el método de una superclase o implementa un método de una clase o interfaz abstracta.

@Override
public int hashCode() {
        return super.hashCode();
}
@Deprecated Marca el código como obsoleto.

@Deprecated
public abstract void method();
@SuppressWarnings Deshabilita las advertencias del compilador para el elemento anotado. Tenga en cuenta que si necesita deshabilitar varias categorías de advertencias, deben encerrarse entre llaves, por ejemplo, @SuppressWarnings({"unchecked", "cast"}) .

public class DocumentsFolder {
   private List documents;

   @SuppressWarnings("unchecked")
public void addDocument(String document) {
            documents.add(document);
   }
}

En este ejemplo, estamos tratando de agregar a una lista que no tiene un tipo definido (un tipo genérico). El compilador nos avisará de esto. Esto es muy útil, pero a veces hay demasiadas "advertencias" y pueden ser ruidosas. Puede usar esta anotación de método y especificar un tipo de advertencia del compilador como argumento. Hay muchos marcadores, así que no se preocupe por recordarlos todos; IDEA generalmente le dirá cuál agregar.

Otro ejemplo con múltiples argumentos:


@SuppressWarnings({"unchecked", "deprecated"})