There are occasions when it is advisable affiliate metadata, or information that describes information, with courses, strategies, or different components in your Java code. For instance, your group may must determine unfinished courses in a big utility. For every unfinished class, the metadata would come with the identify of the developer accountable for ending the category and the category’s anticipated completion date.
Earlier than Java 5, feedback had been Java’s solely versatile mechanism for associating metadata with utility components. However as a result of the compiler ignores them, feedback will not be obtainable at runtime. And even when they had been obtainable, you would need to parse the textual content to acquire essential information gadgets. With out standardizing how the info gadgets had been specified, they could be not possible to parse.
Java 5 modified all the pieces by introducing annotations, a typical mechanism for associating metadata with numerous utility components. This tutorial introduces you to Java annotations.
What you will study on this Java tutorial
- The 4 components of a Java annotation
- Utilizing
@interface
to declare annotation sorts - Meta-annotation sorts and the issue of flexibility
- How one can course of annotations
- Java’s pre-defined annotation sorts
Parts of a Java annotation
An annotation in Java consists of 4 components:
- An
@interface
mechanism for declaring annotation sorts. - Meta-annotation sorts, which you should use to determine the appliance components an annotation sort applies to, determine the lifetime of an annotation (an occasion of an annotation sort), and extra.
- Help for annotation processing by way of an extension to the Java Reflection API and a generalized software for processing annotations.
- Java’s customary (pre-defined) annotation sorts.
You will learn to use every of those components in your Java annotations.
Utilizing @interface to declare annotation sorts
You possibly can declare an annotation sort by specifying the @
image instantly adopted by the interface
reserved phrase and an identifier. For instance, Itemizing 1 declares a easy annotation sort that you simply may use to annotate thread-safe code.
Itemizing 1. ThreadSafe.java
public @interface ThreadSafe
{
}
After declaring this annotation sort, you’d prefix the strategies that you simply thought-about thread-safe with cases of this sort by including the @
image adopted by the kind identify to the tactic headers.
Itemizing 2 reveals a easy instance the place the most important()
technique is annotated @ThreadSafe
.
Itemizing 2. AnnDemo.java (model 1)
public class AnnDemo
{
@ThreadSafe
public static void most important(String[] args)
{
}
}
ThreadSafe
cases provide no metadata apart from the annotation sort identify. Nevertheless, you may provide metadata by including components to this sort, the place an factor is a technique header positioned within the annotation sort’s physique.
In addition to not having code our bodies, components are topic to the next restrictions:
- The strategy header can not declare parameters.
- The strategy header can not present a throws clause.
- The strategy header’s return sort have to be a primitive sort (e.g.,
int
),java.lang.String
,java.lang.Class
, an enum, an annotation sort, or an array of one in every of these sorts. No different sort might be specified for the return sort.
As one other instance, Itemizing 3 presents a ToDo
annotation sort with three components figuring out a specific coding job, specifying the date when the job is to be completed, and naming the coder accountable for finishing the job.
Itemizing 3. ToDo.java (model 1)
public @interface ToDo
{
int id();
String finishDate();
String coder() default "n/a";
}
Observe that every factor declares no parameter(s) or throws clause, has a authorized return sort (int
or String
), and terminates with a semicolon. Additionally, the ultimate factor reveals {that a} default return worth might be specified; this worth is returned when an annotation doesn’t assign a price to the factor.
Itemizing 4 makes use of ToDo
to annotate an unfinished class technique.
Itemizing 4. AnnDemo.java (model 2)
public class AnnDemo
{
public static void most important(String[] args)
{
String[] cities = { "New York", "Melbourne", "Beijing", "Moscow",
"Paris", "London" };
kind(cities);
}
@ToDo(id = 1000, finishDate = "10/10/2019", coder = "John Doe")
static void kind(Object[] objects)
{
}
}
Itemizing 4 assigns a metadata merchandise to every factor; for instance, 1000
is assigned to id
. In contrast to coder
, the id
and finishDate
components have to be specified; in any other case, the compiler will report an error. When coder
isn’t assigned a price, it assumes its default "n/a"
worth.
Java offers a particular String worth()
factor that can be utilized to return a comma-separated checklist of metadata gadgets. Itemizing 5 demonstrates this factor in a refactored model of ToDo
.
Itemizing 5. ToDo.java (model 2)
public @interface ToDo
{
String worth();
}
When worth()
is an annotation sort’s solely factor, you don’t should specify worth
and the =
project operator when assigning a string to this factor. Itemizing 6 demonstrates each approaches.
Itemizing 6. AnnDemo.java (model 3)
public class AnnDemo
{
public static void most important(String[] args)
{
String[] cities = { "New York", "Melbourne", "Beijing", "Moscow",
"Paris", "London" };
kind(cities);
}
@ToDo(worth = "1000,10/10/2019,John Doe")
static void kind(Object[] objects)
{
}
@ToDo("1000,10/10/2019,John Doe")
static boolean search(Object[] objects, Object key)
{
return false;
}
}
Meta-annotation sorts and the issue of flexibility
You possibly can annotate sorts (e.g., courses), strategies, native variables, and extra. Nevertheless, this flexibility might be problematic. For instance, you may wish to limit ToDo
to strategies solely, however nothing prevents it from getting used to annotate different utility components, as demonstrated in Itemizing 7.
Itemizing 7. AnnDemo.java (model 4)
@ToDo("1000,10/10/2019,John Doe")
public class AnnDemo
{
public static void most important(String[] args)
{
@ToDo(worth = "1000,10/10/2019,John Doe")
String[] cities = { "New York", "Melbourne", "Beijing", "Moscow",
"Paris", "London" };
kind(cities);
}
@ToDo(worth = "1000,10/10/2019,John Doe")
static void kind(Object[] objects)
{
}
@ToDo("1000,10/10/2019,John Doe")
static boolean search(Object[] objects, Object key)
{
return false;
}
}
In Itemizing 7, ToDo
can be used to annotate the AnnDemo
class and cities
native variable. The presence of those faulty annotations may confuse somebody reviewing your code, and even your personal annotation processing instruments. For the instances when it is advisable slim an annotation sort’s flexibility, Java presents the Goal
annotation sort in its java.lang.annotation
package deal.
Goal
is a meta-annotation sort—an annotation sort for annotating annotation sorts. That is totally different from a non-meta-annotation sort, whose annotations annotate utility components akin to courses and strategies. The Goal
annotation sort identifies the sorts of utility components to which an annotation sort is relevant. These components are recognized by Goal
’s ElementValue[] worth()
factor.
java.lang.annotation.ElementType
is an enum whose constants describe utility components. For instance, CONSTRUCTOR
applies to constructors and PARAMETER
applies to parameters. Itemizing 8 refactors Itemizing 5’s ToDo
annotation sort to limit it to strategies solely.
Itemizing 8. ToDo.java (model 3)
import java.lang.annotation.ElementType;
import java.lang.annotation.Goal;
@Goal({ElementType.METHOD})
public @interface ToDo
{
String worth();
}
Given the refactored ToDo
annotation sort, an try and compile Itemizing 7 now ends in the next error message:
AnnDemo.java:1: error: annotation sort not relevant to this type of declaration
@ToDo("1000,10/10/2019,John Doe")
^
AnnDemo.java:6: error: annotation sort not relevant to this type of declaration
@ToDo(worth="1000,10/10/2019,John Doe")
^
2 errors
Further meta-annotation sorts
Java 5 launched three necessary meta-annotation sorts, that are discovered within the java.lang.annotation
package deal:
Retention
signifies how lengthy annotations with the annotated sort are to be retained. This sort’s relatedjava.lang.annotation.RetentionPolicy
enum declares the next constants:CLASS
: The compiler information annotations in a category file and the digital machine doesn’t retain them. That is the default coverageRUNTIME
: The compiler information annotations in a category file and the digital machine retains them.SOURCE
: The compiler discards annotations.
Documented
signifies that cases ofDocumented
-annotated annotations are to be documented byjavadoc
and related instruments.Inherited
signifies that an annotation sort is routinely inherited.
One other meta-annotation sort, launched in Java 8, is java.lang.annotation.Repeatable
. Repeatable
is used to point that the annotation sort whose declaration it (meta-)annotates is repeatable. In different phrases, you may apply a number of annotations from the identical repeatable annotation sort to an utility factor, as demonstrated right here:
@ToDo(worth = "1000,10/10/2019,John Doe")
@ToDo(worth = "1001,10/10/2019,Kate Doe")
static void kind(Object[] objects)
{
}
This instance assumes that ToDo
has been annotated with the Repeatable
annotation sort.
How one can course of annotations
Annotations are supposed to be processed; in any other case, there’s no level in having them. Java 5 prolonged the Java Reflection API that can assist you create your personal annotation processing instruments. For instance, Class
declares an Annotation[]
technique that returns an array of
getAnnotations()java.lang.Annotation
cases. These cases describe annotations current on the factor described by the Class
object.
Itemizing 9 presents a easy utility that hundreds a category file, interrogates its strategies for ToDo
annotations, and outputs the elements of every discovered annotation.
Itemizing 9. AnnProcDemo.java
import java.lang.replicate.Methodology;
public class AnnProcDemo
{
public static void most important(String[] args) throws Exception
{
if (args.size != 1)
{
System.err.println("utilization: java AnnProcDemo classfile");
return;
}
Methodology[] strategies = Class.forName(args[0]).getMethods();
for (int i = 0; i < strategies.size; i++)
{
if (strategies[i].isAnnotationPresent(ToDo.class))
{
ToDo todo = strategies[i].getAnnotation(ToDo.class);
String[] elements = todo.worth().cut up(",");
System.out.printf("ID = %spercentn", elements[0]);
System.out.printf("End date = %spercentn", elements[1]);
System.out.printf("Coder = %spercentnpercentn", elements[2]);
}
}
}
}
After verifying that precisely one command-line argument (figuring out a category file) has been specified, most important()
hundreds the category file by way of Class.forName()
, invokes getMethods()
to return an array of java.lang.replicate.Methodology
objects figuring out all public
strategies within the class file, and processes these strategies.
Methodology processing begins by invoking Methodology
’s boolean isAnnotationPresent(Class<? extends
technique to find out if the annotation described by
Annotation> annotationClass)ToDo.class
is current on the tactic. If that’s the case, Methodology
’s <T extends Annotation> T getAnnotation(Class<T>
technique is named to acquire the annotation.
annotationClass)
The ToDo
annotations which might be processed are these whose sorts declare a single String worth()
factor (see Itemizing 5). As a result of this factor’s string-based metadata is comma-separated, it must be cut up into an array of element values. Every of the three element values is then accessed and output.
Compile this supply code (javac AnnProcDemo.java
). Earlier than you may run the appliance, you’ll want an appropriate class file with @ToDo
annotations on its public
strategies. For instance, you might modify Itemizing 6’s AnnDemo
supply code to incorporate public
in its kind()
and search()
technique headers. You’ll additionally want Itemizing 10’s ToDo
annotation sort, which requires the RUNTIME
retention coverage:
Itemizing 10. ToDo.java (model 4)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Goal;
@Goal({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ToDo
{
String worth();
}
Compile the modified AnnDemo.java
and Itemizing 10, and execute the next command to course of AnnDemo
’s ToDo
annotations:
java AnnProcDemo AnnDemo
If all goes properly, you need to observe the next output:
ID = 1000
End date = 10/10/2019
Coder = John Doe
ID = 1000
End date = 10/10/2019
Coder = John Doe
Java’s pre-defined annotation sorts
Together with the Goal
, Retention
, Documented
, and Inherited
meta-annotation sorts, Java 5 launched Deprecated
, Override
, and SuppressWarnings
as pre-defined annotation sorts. These three annotation sorts are designed for use in a compiler context solely, so their retention insurance policies are set to SOURCE
.
Deprecated
Deprecated
annotates utility components which might be to be deprecated, which means they will be phased out and shouldn’t be used. The compiler will warn you when a deprecated factor is being accessed.
The next java.util.Date
constructor demonstrates Deprecated
:
@Deprecated
public Date(int yr, int month, int date, int hrs, int min)
{
// ... physique of this constructor
}