100 votes

Comment les annotations telles que @Override fonctionnent-elles en interne en Java ?

Est-ce que quelqu'un pourrait m'expliquer comment fonctionnent les annotations en interne en Java?

Je sais comment créer des annotations personnalisées en utilisant la bibliothèque java.lang.annotation en Java. Mais je ne comprends toujours pas comment cela fonctionne en interne, par exemple, l'annotation @Override.

Je vous serais vraiment reconnaissant si quelqu'un pouvait expliquer cela en détail.

148voto

chrylis Points 22655

La première distinction principale entre les types d'annotations est de savoir si elles sont utilisées au moment de la compilation et ensuite jetées (comme @Override) ou placées dans le fichier de classe compilé et disponibles à l'exécution (comme @Component de Spring). Cela est déterminé par la politique de rétention de l'annotation. Si vous écrivez votre propre annotation, vous devriez décider si l'annotation est utile lors de l'exécution (pour l'auto-configuration, peut-être) ou seulement au moment de la compilation (pour la vérification ou la génération de code).

Lors de la compilation du code avec des annotations, le compilateur voit l'annotation comme il voit les autres modificateurs sur les éléments source, comme les modificateurs d'accès (public/private) ou final. Lorsqu'il rencontre une annotation, il exécute un processeur d'annotation, qui est comme une classe de plug-in qui dit qu'il est intéressé par une annotation spécifique. Le processeur d'annotation utilise généralement l'API de Réflexion pour inspecter les éléments en cours de compilation et peut simplement effectuer des vérifications sur eux, les modifier ou générer un nouveau code à compiler. @Override est un exemple du premier cas ; il utilise l'API de Réflexion pour s'assurer qu'il peut trouver une correspondance pour la signature de méthode dans l'une des superclasses et utilise Messager pour provoquer une erreur de compilation s'il ne peut pas le faire.

Il existe un certain nombre de tutoriels disponibles sur l'écriture de processeurs d'annotations; voici un utile. Parcourez les méthodes sur l'interface Processor pour voir comment le compilateur invoque un processeur d'annotation; l'opération principale se déroule dans la méthode process, qui est appelée chaque fois que le compilateur voit un élément qui a une annotation correspondante.

46voto

upma Points 517

Outre ce que d'autres ont suggéré, je vous recommande d'écrire une annotation personnalisée et son processeur à partir de zéro pour voir comment fonctionne l'annotation.

Dans mon cas, par exemple, j'ai écrit une annotation pour vérifier si les méthodes sont surchargées au moment de la compilation.

Tout d'abord, créez une annotation nommée Overload. Cette annotation est appliquée à la méthode donc je l'annote avec @Target(value=ElementType.METHOD)

package gearon.customAnnotation;

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

@Target(value=ElementType.METHOD)
public @interface Overload {

}

Ensuite, créez un processeur correspondant pour gérer les éléments annotés par l'annotation définie. Pour la méthode annotée par @Overload, sa signature doit apparaître plus d'une fois. Sinon une erreur est affichée.

package gearon.customAnnotation;

import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;

@SupportedAnnotationTypes("gearon.customAnnotation.Overload")

public class OverloadProcessor extends AbstractProcessor{

    @Override
    public boolean process(Set annotations, RoundEnvironment roundEnv) {
        // TODO Auto-generated method stub
        HashMap map = new HashMap();

        for(Element element : roundEnv.getElementsAnnotatedWith(Overload.class)){
            String signature = element.getSimpleName().toString();
            int count = map.containsKey(signature) ? map.get(signature) : 0;
            map.put(signature, ++count);
        }

        for(Entry entry: map.entrySet()){
            if(entry.getValue() == 1){
                processingEnv.getMessager().printMessage(Kind.ERROR, "La méthode dont la signature est " + entry.getKey() +  " n'a pas été surchargée");
            }
        }
        return true;
    }
}

Après avoir empaqueté l'annotation et son processeur dans un fichier jar, créez une classe avec @Overload et utilisez javac.exe pour la compiler.

import gearon.customAnnotation.Overload;

public class OverloadTest {
    @Overload
    public static void foo(){
    }

    @Overload
    public static void foo(String s){

    }

    @Overload
    public static void nonOverloadedMethod(){

    }
} 

Comme la méthode nonOverloadedMethod() n'a pas été effectivement surchargée, nous obtiendrons une sortie comme ci-dessous:

description de l'image

6voto

Matt Ball Points 165937

Voici @Override : http://www.docjar.com/html/api/java/lang/Override.java.html.

Il n'y a rien de spécial à ce sujet qui le différencie d'une annotation que vous pourriez écrire vous-même. Les éléments intéressants se trouvent dans les consommateurs des annotations. Pour une annotation comme @Override, cela se trouverait dans le compilateur Java lui-même, ou un outil d'analyse de code statique, ou votre IDE.

3voto

Suivez ce lien. Cela fournira une réponse précise à votre problème. Si nous nous concentrons sur les annotations en Java, les Annotations ont été introduites en Java 5 et ne sont pas spécifiques à Spring. En général, les annotations vous permettent d'ajouter des métadonnées à une classe, une méthode ou une variable. Une annotation peut être interprétée par le compilateur (par exemple, l'annotation @Override) ou par un framework tel que Spring (par exemple, l'annotation @Component).

En plus j'ajoute plus de références.

  1. http://www.codeproject.com/Articles/272736/Understanding-Annotations-in-Java
  2. http://docs.oracle.com/javase/7/docs/api/java/lang/annotation/package-summary.html
  3. http://www.coderanch.com/how-to/java/AnnotationsExample

3voto

Thomas Points 35713

Fondamentalement, les annotations ne sont que des marqueurs lus par le compilateur ou l'application. En fonction de leur politique de rétention, elles sont disponibles uniquement au moment de la compilation ou sont lisibles à l'exécution à l'aide de la réflexion.

De nombreux frameworks utilisent la rétention à l'exécution, c'est-à-dire qu'ils vérifient de manière réflective si certaines annotations sont présentes sur une classe, une méthode, un champ, etc. et font quelque chose si l'annotation est présente (ou non). De plus, les membres des annotations peuvent être utilisés pour transmettre des informations supplémentaires.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X