107

Can anybody explain to me how annotations work internally in java?

I know how we can create custom annotations by using java.lang.annotation library in java. But I still don't get how it's working internally for example, the @Override annotation.

I will be really thankful if anyone could explain that in detail.

Rishabh
  • 13
  • 3
Chirag Dasani
  • 1,205
  • 2
  • 10
  • 11
  • 5
    What do you mean by "work internally"? The compiler? The runtime? – chrylis -cautiouslyoptimistic- Aug 12 '13 at 14:45
  • 6
    @chrylis Work internally means how it's automatic identified that this method is override method or this one is not override method. It's work on both time. like override annotation work in compile time and spring controller annotation is work in runtime – Chirag Dasani Aug 13 '13 at 06:45

6 Answers6

154

The first main distinction between kinds of annotation is whether they're used at compile time and then discarded (like @Override) or placed in the compiled class file and available at runtime (like Spring's @Component). This is determined by the @Retention policy of the annotation. If you're writing your own annotation, you'd need to decide whether the annotation is helpful at runtime (for autoconfiguration, perhaps) or only at compile time (for checking or code generation).

When compiling code with annotations, the compiler sees the annotation just like it sees other modifiers on source elements, like access modifiers (public/private) or final. When it encounters an annotation, it runs an annotation processor, which is like a plug-in class that says it's interested a specific annotation. The annotation processor generally uses the Reflection API to inspect the elements being compiled and may simply run checks on them, modify them, or generate new code to be compiled. @Override is an example of the first; it uses the Reflection API to make sure it can find a match for the method signature in one of the superclasses and uses the Messager to cause a compile error if it can't.

There are a number of tutorials available on writing annotation processors; here's a useful one. Look through the methods on the Processor interface for how the compiler invokes an annotation processor; the main operation takes place in the process method, which gets called every time the compiler sees an element that has a matching annotation.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
49

Besides what others suggested, I recommend you write a customized annotation and its processor from scratch to see how annotation works.

In my own, for example, I have written an annotation to check whether methods are overloaded in compile time.

Firstly, create an annotation named Overload. This annotation is applied to method so I annotate it with @Target(value=ElementType.METHOD)

package gearon.customAnnotation;

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

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

}

Next, create corresponding processor to handle elements annotated by defined annotation. For method annotated by @Overload, its signature must appear more than one time. Or the error is printed.

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<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        // TODO Auto-generated method stub
        HashMap<String, Integer> map = new HashMap<String, Integer>();

        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<String, Integer> entry: map.entrySet()){
            if(entry.getValue() == 1){
                processingEnv.getMessager().printMessage(Kind.ERROR, "The method which signature is " + entry.getKey() +  " has not been overloaded");
            }
        }
        return true;
    }
}

After packaging annotation and its process into a jar file, create a class with @Overload and use javac.exe to compile it.

import gearon.customAnnotation.Overload;

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

    @Overload
    public static void foo(String s){

    }

    @Overload
    public static void nonOverloadedMethod(){

    }
} 

Since nonOverloadedMethod() has not actually been overloaded, we will get the output like below:

enter image description here

Eugene
  • 10,627
  • 5
  • 49
  • 67
  • Above info is very good respect to JDK6(+1 for that), but how to achieve the same thing using JDK5 as well? Using JDK6 SupportedAnnotationTypes, AbstractProcessor class it became simpler but how the same thing happened in the past(like Spring FrameWork 2.5 on jdk5)?How JVM detect annotation processor like class in jdk5? can you please guide by editing the answer in 2 section(one for JDK5,Current Version Is For Jdk6+)? – prajitgandhi Jan 29 '17 at 19:12
  • In your class `OverloadProcessor::process` why it's `entry.getValue() == 1`? One don't have to add an annotation at the parent class/interface, so `roundEnv.getElementsAnnotatedWith(Overload.class)` won't get the parent class/interface, right? – NeoZoom.lua Oct 16 '19 at 02:51
  • 1
    I'm confused at this part but I think your answer is very helpful. – NeoZoom.lua Oct 16 '19 at 02:54
  • @s̮̦̩e̝͓c̮͔̞ṛ̖̖e̬̣̦t̸͉̥̳̼ If a method is treated as Overload, there should be at least another method with same name defined in the Class. – Eugene Oct 16 '19 at 03:11
  • 1
    @Raining for a method to say Overloaded, it must appear more than once in the same class, but if it is ` == 1` then its an error. – KrishPrabakar Jun 17 '20 at 14:02
  • Hi, @Eugene Thanks for your answer. I have a probelom, I just wanna put this 3 java file in same directory, no use package keyword. So what should `@SupportedAnnotationTypes("gearon.customAnnotation.Overload")` changed to? I've test `@SupportedAnnotationTypes("Overload")` not worked. And then I mkdir gearon/customAnnotation and put Overload.java and OverloadProcessor.java in there run javac no any error report. – roachsinai Apr 28 '21 at 11:28
  • I created jar and in separate project in IntelliJ imported jar and added test class there with @Overload annotation for methods. But I didn't see any compile time error there in IDE. From command line I have to passed -processor tag and there it is giving proper error. Please let me know why processor is not picked in IDE. – IfOnly Mar 21 '23 at 13:53
6

Here's @Override: http://www.docjar.com/html/api/java/lang/Override.java.html.

There's nothing special about it that differentiates it from an annotation you might write yourself. The interesting bits are in the consumers of the annotations. For an annotation like @Override, that would be in the Java compiler itself, or a static code analysis tool, or your IDE.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 1
    I know that source code of Override annotation. But how it's work internally. like how it can be identified this method is not override method or this one is override method? or can i create my custom override annotation? and it should be works exactly same behavior like java override annotation – Chirag Dasani Aug 13 '13 at 06:31
  • 3
    As I said in my answer, **the behavior is not part of the annotation.** The interpretation lies in the things which consume the annotation. Because of that, unless you change the consumer, you can't practically create your own custom version of `@Override` (or other standard annotations). – Matt Ball Aug 13 '13 at 13:55
3

Follow this link. This will provide close answer for your problem. If we focused on annotations in Java, Annotations were introduced in Java 5 and are not Spring specific. In general, annotations allow you to add metadata to a class, method or variable. An annotation can be interpreted by the compiler (for example, the @Override annotation) or by a framework such as spring (for example, the @Component annotation).

In addition I am adding more references.

  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
Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115
  • @LuiggiMendoza java 1.7 annotation doc added – Ruchira Gayan Ranaweera Aug 12 '13 at 16:44
  • @Ruchira i was opened all links but still i am not cleared how it's work. Can u explain me in details like consider as spring annotations. I can do all the things by using annotation without write any configuration in spring.xml file. is it internally bind annotation to xml configuration? – Chirag Dasani Aug 13 '13 at 06:50
  • @ChiragDasani take a look at this. this may help you http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s11.html and also see this SO post http://stackoverflow.com/questions/2798181/what-are-annotations-and-how-do-they-actually-work-for-frameworks-like-spring – Ruchira Gayan Ranaweera Aug 13 '13 at 06:53
3

Basically, annotations are just markers which are read by the compiler or the application. Depending on their retention policy they are available at compile time only or are readable at runtime using reflection.

Many frameworks use runtime retention, i.e. they reflectively check whether some annotations are present on a class, method, field etc. and do something if the annotation is present (or not). Additionally, members of annotations can be used to pass further information.

Thomas
  • 87,414
  • 12
  • 119
  • 157
0

Even I was looking for the answer of the same question. the below link provided the consolidated good stuff to get the inside of annotations. https://dzone.com/articles/how-annotations-work-java Hope it helps!

Kusum
  • 241
  • 5
  • 20