Java annotations
A set of annotation types are predefined in the Java SE API. Some annotation types are used by the Java compiler, and some apply to other annotations. Let's discover it!
@Inherited
@Inherited annotation indicates that the annotation type can be inherited from the superclass.
(This is not true by default.)
This is an annotation for annotations.
It means that subclasses of annotated classes are considered having the same annotation as their superclass.
public class Test { @Inherited @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface VVInherited { } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface VVNone { } @VVNone class A { } @VVInherited class B extends A { } class C extends B { } public static void main(String[] args) { out(new Test().new A().getClass().getAnnotation(VVInherited.class)); out(new Test().new B().getClass().getAnnotation(VVInherited.class)); out(new Test().new C().getClass().getAnnotation(VVInherited.class)); out(""); out(new Test().new A().getClass().getAnnotation(VVNone.class)); out(new Test().new B().getClass().getAnnotation(VVNone.class)); out(new Test().new C().getClass().getAnnotation(VVNone.class)); } static void out(Object o) { System.out.println(o); } }
null
@vv.Test$VVInherited()
@vv.Test$VVInherited()
@vv.Test$VVNone()
null
null
@Target
Define
@Target is an annotation that applies to other annotations.
Annotations that apply to other annotations are called meta-annotations.
There are several meta-annotation types defined in java.lang.annotation.
@Target annotation marks another annotation to restrict what kind of Java elements the annotation can be applied to.
A target annotation specifies one of the following element types as its value:
- ElementType.ANNOTATION_TYPE can be applied to an annotation type.
- ElementType.CONSTRUCTOR can be applied to a constructor.
- ElementType.FIELD can be applied to a field or property.
- ElementType.LOCAL_VARIABLE can be applied to a local variable.
- ElementType.METHOD can be applied to a method-level annotation.
- ElementType.PACKAGE can be applied to a package declaration.
- ElementType.PARAMETER can be applied to the parameters of a method.
- ElementType.TYPE can be applied to any element of a class.
With JDK11 there are also:
- ElementType.MODULE
- ElementType.TYPE_PARAMETER
Snippet
@Target({ElementType.FIELD, ElementType.METHOD}) public @interface MyFieldOrMethodAnnotation{ ... }
@Repeatable
Define
There are some situations where you want to apply the same annotation to a declaration or type use. As of the Java SE 8 release, repeating annotations enable you to do this.
- The annotation type java.lang.annotation.Repeatable is used to indicate that the annotation type whose declaration it (meta-)annotates is repeatable.
- The value of @Repeatable indicates the containing annotation type for the repeatable annotation type.
Snippet
―Purpose
Set a timer to run a method, doPeriodicCleanup, on the last day of the month, and on every Friday at 11:00 p.m.
―Use
@Schedule(dayOfMonth="last") @Schedule(dayOfWeek="Fri", hour="23") public void doPeriodicCleanup() { ... }
―Thanks to
import java.lang.annotation.Repeatable; @Repeatable(Schedules.class) public @interface Schedule { String dayOfMonth() default "first"; String dayOfWeek() default "Mon"; int hour() default 12; }
―And thanks to
public @interface Schedules { Schedule[] value(); }
@Override & @SuppressWarnings
@Override annotation informs the compiler that the element is meant to override an element declared in a superclass.
public @interface Schedules { Schedule[] value(); }
@SuppressWarnings annotation tells the compiler to suppress specific warnings that it would otherwise generate.
// use a deprecated method and tell // compiler not to generate a warning @SuppressWarnings("deprecation") void useDeprecatedMethod() { // deprecation warning // - suppressed objectOne.deprecatedMethod(); }
@SafeVarargs
Define
Like @SupressWarnings but for varargs parameters.
@SafeVarargs annotation, when applied to a method or constructor, asserts that the code does not perform potentially unsafe operations on its varargs parameter.
When this annotation type is used, unchecked warnings relating to varargs usage are suppressed.
Cause
Before Java 9 versions, if vararg methods are used with generics, then there is a warning message. Even though not all methods create heap pollution, compiler shows warning for all vararg methods used with generics. That's the reason @SafeVarargs concept was added to Java 9 version to avoid these warnings.
Conclusion
So use @SafeVarargs annotation on final or static methods and constructors.
@SafeVarargs is like @SupressWarnings in that it allows us to declare that a particular compiler warning is a false positive.
Snippet
public class Machine<T> { private List<T> versions = new ArrayList<>(); @SafeVarargs public final void safe(T... toAdd) { for (T version : toAdd) { versions.add(version); } } }
@FunctionalInterface
Define
Indicates that the type declaration is intended to be a functional interface.
―An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface as defined by the Java Language Specification. Conceptually, a functional interface has exactly one abstract method.
―Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.
―If a type is annotated with this annotation type, compilers are required to generate an error message unless:
- The type is an interface type and not an annotation type, enum, or class.
- The annotated type satisfies the requirements of a functional interface.
Snippet
@FunctionalInterface interface sayable{ void say(String msg); } public class FunctionalInterfaceExample implements sayable{ public void say(String msg){ System.out.println(msg); } public static void main(String[] args) { FunctionalInterfaceExample fie = new FunctionalInterfaceExample(); fie.say("Hello there"); } }
@Deprecated
Define
@Deprecated 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. The use of the at-sign (@) in both Javadoc comments and in annotations is not coincidental: they are related conceptually. Also, note that the Javadoc tag starts with a lowercased and the annotation starts with an uppercase D.
Snippet
// Javadoc comment follows /** * @deprecated * explanation of why it was deprecated */ @Deprecated static void deprecatedMethod() { } }
@Retention
Define
@Retention annotation specifies how the marked annotation is stored:
RetentionPolicy.SOURCE – The marked annotation is retained only in the source level and is ignored by the compiler.
RetentionPolicy.CLASS – The marked annotation is retained by the compiler at compile time, but is ignored by the Java Virtual Machine (JVM).
RetentionPolicy.RUNTIME – The marked annotation is retained by the JVM so it can be used by the runtime environment.
Snippet
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface MySampleAnn { String name(); String desc(); } class MyAnnTest{ @MySampleAnn(name = "test1", desc = "testing annotations") public void myTestMethod(){ //method implementation } }
@Documented
Define
@Documented annotation indicates that whenever the specified annotation is used those elements should be documented using the Javadoc tool. (By default, annotations are not included in Javadoc.)
But if @Documented is used, it then will be processed by javadoc-like tools and the annotation type information will also be included in the generated document.
Snippet
Given:
@Documented public @interface Test_Documented { String doTestDocument(); }
Next, we define TestAnnotations class as follows:
public class TestAnnotations { public static void main(String arg[]) { new TestAnnotations().doSomeTestDocumented(); } @Test_Documented(doTestDocument="Hello document") public void doSomeTestDocumented() { System.out.printf("Testing annotation 'Documented'"); } }
There will be annotation-type information for the doSomeTestDocumented() method in the JavaDoc:
This is because of the @Documented tag attached to your Test_Documented annotation.
Links
- https://docs.oracle.com/javase/tutorial/java/annotations/predefined.html
- https://www.developer.com/java/other/article.php/10936_3556176_3/An-Introduction-to-Java-Annotations.htm
- https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Deprecated.html
- https://docs.oracle.com/javase/9/docs/api/java/lang/SafeVarargs.html
- https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/Repeatable.html
