Java Custom Annotations Example
custom
annotation
java
Annotations in Java provide information about the code. Java annotations have no direct effect on the code they annotate but can be used to provide info where the code is being used.
Predefined Annotations in Java
Java Provides some built-in annotations:
@Deprecated - indicates that the marked element is deprecated and should no longer be used.
@Override - informs the compiler that the element is meant to override an element declared in a superclass.
@SuppressWarnings - tells the compiler to suppress specific warnings that it would otherwise generate.
@SafeVarargs - when applied to a method or constructor, asserts that the code does not perform potentially unsafe operations on its varargs
parameter.
@FunctionalInterface - indicates that the type declaration is intended to be a functional interface.
Annotations that applied to other annotations:
@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.
@Documented -annotation indicates that whenever the specified annotation is used those elements should be documented using the Javadoc tool.
@Target - annotation marks another annotation to restrict what kind of Java elements the annotation can be applied to:
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.
@Inherited - annotation indicates that the annotation type can be inherited from the super-class.
@Repeatable - indicates that the marked annotation can be applied more than once to the same declaration or type use.
Custom Annotations
Creating a custom annotation in Java is similar to writing an interface, except that it interface keyword is prefixed with @ symbol.
Code
The example below is designed to be used for a field and the retention is set up to RUNTIME, otherwise, the usage example wouldn't work.
package com.admfactory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Target(ElementType.FIELD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface DBField {
String name();
Class< ?> type();
boolean isPrimaryKey() default false;
}
Usage
Annotated class:
package com.admfactory.annotation;
import java.util.Date;
public class User {
@DBField(name = "id", isPrimaryKey = true, type = Long.class)
private long id;
@DBField(name = "name", type = String.class)
private String name;
@DBField(name = "email", type = String.class)
private String email;
@DBField(name = "created", type = Date.class)
private Date created;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
}
Getting info from an object of an annotated class type using reflection:
package com.admfactory.annotation;
import java.lang.reflect.Field;
import java.util.Date;
public class AnnotationExample {
public static void main(String[] args) throws Exception {
System.out.println("Java Custom Annotation Example");
System.out.println();
User usr = new User();
usr.setEmail("john.doe@example.com");
usr.setName("John Doe");
usr.setId(112);
usr.setCreated(new Date());
for (Field field : usr.getClass().getDeclaredFields()) {
DBField dbField = field.getAnnotation(DBField.class);
System.out.println("field name: " + dbField.name());
/** changed the access to public */
field.setAccessible(true);
Object value = field.get(usr);
System.out.println("field value: " + value);
System.out.println("field type: " + dbField.type());
System.out.println("is primary: " + dbField.isPrimaryKey());
System.out.println();
}
}
}
Output
Java Custom Annotation Example
field name: id
field value: 112
field type: class java.lang.Long
is primary: true
field name: name
field value: John Doe
field type: class java.lang.String
is primary: false
field name: email
field value: john.doe@example.com
field type: class java.lang.String
is primary: false
field name: created
field value: Wed Jul 25 17:10:05 BST 2018
field type: class java.util.Date
is primary: false