Nel 2005, con l'arrivo di Java 5, abbiamo conosciuto nuove entità chiamate annotazioni.

Le annotazioni sono una forma speciale di metadati sintattici che possono essere dichiarati nel codice. Sono utilizzati per analizzare il codice in fase di compilazione o in fase di esecuzione. Puoi pensare a un'annotazione come a un'etichetta, un tag o un suggerimento del compilatore.

Probabilmente ti sei già imbattuto in annotazioni. Ad esempio, quando si esegue l'override di un metodo della classe genitore, si scrive @Override prima del metodo stesso. Questa annotazione indica che il metodo del genitore verrà sovrascritto nella classe figlia.

Sintassi:


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

Voglio notare subito che le annotazioni non si applicano solo ai metodi. Vengono utilizzati con pacchetti, classi, metodi, campi e parametri.

Per capire come funzionano le annotazioni, dobbiamo prima familiarizzare con il concetto di interfaccia marcatore. Dall'avvento di Java, gli sviluppatori hanno sempre avuto bisogno di un modo per contrassegnare le classi per eseguire determinate azioni su di esse.

Prima di Java 5, usavano un'interfaccia che non faceva ciò che ci aspettiamo che facciano le interfacce. Non aveva metodi e nessun contratto. Ha solo contrassegnato una classe come speciale in qualche modo.

Tale interfaccia era chiamata interfaccia marcatore. Dal nome potresti intuire che il suo scopo è contrassegnare le classi per la JVM, il compilatore o qualche libreria. Alcune interfacce marcatore, come Serializable , rimangono. Questa interfaccia marker ci consente di indicare che le istanze di una classe possono essere serializzate.

Come abbiamo visto, le interfacce marker continuano a vivere anche dopo l'introduzione delle annotazioni.

Annotazioni contro interfacce marker:


@MyAnnotation
public class MyClass {}

public class MyClass implements MarkerInterface {}

Entrambi gli approcci hanno lo stesso obiettivo, ma c'è una chiara differenza nella loro attuazione. Ad esempio, considera un'interfaccia e un'annotazione che indica che una classe appartiene a un particolare tipo.

Se stiamo usando un'interfaccia, contrassegniamo la classe. Se lo usiamo in modo errato e si verifica un errore, allora scopriremo il problema durante la compilazione e il programma non funzionerà.

Con le annotazioni, tutto non è così semplice: qui l'errore verrà rilevato in fase di esecuzione, il che significa che il programma verrà avviato, ma, ovviamente, non finirà.

Nota che se dobbiamo contrassegnare una classe per un uso futuro, le sue istanze devono essere passate a un metodo specifico:


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
}

Un'interfaccia marcatore funziona meglio qui.

È meglio usare le annotazioni quando abbiamo bisogno di qualcosa di più, come i parametri supportati dalle annotazioni.

Diamo un'occhiata alle annotazioni standard nel JDK:

Annotazione Descrizione Esempio
@Oltrepassare Specifica che un metodo esegue l'override del metodo di una superclasse o implementa un metodo di una classe astratta o di un'interfaccia.

@Override
public int hashCode() {
        return super.hashCode();
}
@Deprecato Contrassegna il codice come deprecato.

@Deprecated
public abstract void method();
@SuppressWarnings Disabilita gli avvisi del compilatore per l'elemento annotato. Si noti che se è necessario disabilitare più categorie di avvisi, devono essere racchiusi tra parentesi graffe, ad esempio @SuppressWarnings({"unchecked", "cast"}) .

public class DocumentsFolder {
   private List documents;

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

In questo esempio, stiamo cercando di aggiungere a un elenco che non ha un tipo definito (un tipo generico). Il compilatore ci avviserà di questo. Questo è molto utile, ma a volte ci sono troppi "avvisi" e possono essere rumorosi. È possibile utilizzare questa annotazione del metodo e specificare un tipo di avviso del compilatore come argomento. Ci sono molti indicatori, quindi non preoccuparti di ricordarli tutti: IDEA di solito ti dirà quale aggiungere.

Un altro esempio con più argomenti:


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