How and where are Annotations used in Java?
An annotation, in the Java computer programming language, is a special form of syntactic metadata that can be added to Java source code.
Classes, methods, variables, parameters and packages may be annotated. Unlike Javadoc tags, Java annotations can be reflective in that they can be embedded in class files generated by the compiler and may be retained by the Java VM to be made retrievable at run-time.
It is possible to create meta-annotations out of the existing ones in Java, which makes this concept more sophisticated.
Java defines a set of annotations that are built into the language.
Annotations applied to java code:
- @Override – Checks that the function is an override. Causes a compile warning if the function is not found in one of the parent classes.
- @Deprecated – Marks the function as obsolete. Causes a compile warning if the function is used.
- @SuppressWarnings – Instructs the compiler to suppress the compile time warnings specified in the annotation parameters.
Annotations applied to other annotations:
- @Retention – Specifies how the marked annotation is stored—Whether in code only, compiled into the class, or available at runtime through reflection.
- @Documented – Marks another annotation for inclusion in the documentation.
- @Target – Marks another annotation to restrict what kind of java elements the annotation may be applied to.
- @Inherited – Marks another annotation to be inherited to subclasses of annotated class (by default annotations are not inherited to subclasses).
Let’s take a look at these via sample Examples:
1) @Override Annotation:
Its presence indicates to the compiler that the annotated method must override an existing superclass method.
The most common use case for @Override is with Object methods:
@Override public int hashValue(){ System.out.Println("This method is using @Override Annotation"); }
The main reason @Override was created was to deal with simple typographical errors.
For example, a method mistakenly declared as
public int hashvalue(){...}
is in fact not an override – the method name has all lower case letters, so it doesn’t exactly match the name of the hashValue()method. It will however compile perfectly well. Such an error is easy to make, and difficult to catch, which is a dangerous combination. Using the @Override annotation prevents you from making such errors.
You should be in the habit of using @Override whenever you override a superclass method.
2) @Deprecated Annotation:
This annotation indicates that the marked element is deprecated and should no longer be used. The compiler generates a warning whenever a program uses a method, class, or field with the @Deprecated
annotation.
When an element is deprecated, it should also be documented using the Javadoc @deprecated
tag, as shown in the following example.
@Deprecated static void deprecatedMethod() { System.out.Println("This method is Deprecated.."); }
3) @SuppressWarnings Annotation:
Just tell compiler, please don’t shout. I know what I’m doing 🙂 .
@SuppressWarnings("serial") public class OldCode implements Serializable{ System.out.Println("This is Old Code.."); }
4) @Retention Annotation:
The retention annotation indicates where and how long annotations with this type are to be retained.
There are three values:
- RetentionPolicy.SOURCE—Annotations with this type will be by retained only at the source level and will be ignored by the compiler.
- RetentionPolicy.CLASS—Annotations with this type will be by retained by the compiler at compile time, but will be ignored by the VM.
- RetentionPolicy.RUNTIME—Annotations with this type will be retained by the VM so they can be read only at run-time.
@Retention(RetentionPolicy.RUNTIME) public @interface Crunchify_Retention { String returnSomething(); }
5) @Documented Annotation:
@Documented public @interface Crunchify_Documented { String writeDocument(); }public class DocumentedAnnotations { public static void main(String arg[]) { new DocumentedAnnotations().performRetention(); new DocumentedAnnotations().performDocumented(); } @ Crunchify_Retention (returnSomething="Hello retention test") public void performRetention() { System.out.printf("Testing annotation 'Crunchify_Retention'"); } @Crunchify_Documented(writeDocument="Hello document") public void performDocumented() { System.out.printf("Testing annotation 'Crunchify_Documented'"); } }
Now try to run Java Doc command and see output.
6) @Target Annotation:
Target indicates which program element(s) can be annotated using instances of the annotated annotation type. The value of Target is one of the members of the java.lang.annotation.ElementType
enum:
- ANNOTATION_TYPE. The annotated annotation type can be used to annotate annotation type declaration.
- CONSTRUCTOR. The annotated annotation type can be used to annotate constructor declaration.
- FIELD. The annotated annotation type can be used to annotate field declaration.
- LOCAL_VARIABLE. The annotated annotation type can be used to annotate local variable declaration.
- METHOD. The annotated annotation type can be used to annotate method declaration.
- PACKAGE. The annotated annotation type can be used to annotate package declarations.
- PARAMETER. The annotated annotation type can be used to annotate parameter declarations.
- TYPE. The annotated annotation type can be used to annotate type declarations.
@Target(value=METHOD) You can have multiple values in the Target annotation. @Target(value={TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
7) @Inherited Annotation:
Exactly as the name sounds, an @Inherited
annotation type is inherited by subclasses of an annotated type.
@Inherited @interface ForEveryone { } @interface JustForMe { } @ForEveryone @JustForMe class Superclass { } class Subclass extends Superclass { }
In this example, Superclass
has been explicitly annotated with both @ForEveryone
and @JustForMe
. Subclass
hasn’t been explicitly marked with either one; however, it inherits @ForEveryone
because the latter is annotated with @Inherited
.
@JustForMe
isn’t annotated, so it isn’t inherited by Subclass
.