Java custom annotations
Java annotations are some meta information attached to the code, which is used for parsing and using some tools during compilation and runtime, and serve as explanation and configuration functions.
Annotations will not and cannot affect the actual logic of the code, and only play a auxiliary role. Included in the java.lang.annotation package.
1. Meta Note
Meta-annotation refers to the annotation of the annotation. Including four types: @Retention @Target @Document @Inherited.
1.1. @Retention: Define the retention strategy of annotations
@Retention(RetentionPolicy.SOURCE) //The annotation only exists in the source code and does not contain @Retention(RetentionPolicy.CLASS) // The default retention policy is used. The annotation will exist in the class bytecode file, but it cannot be obtained at runtime. @Retention(RetentionPolicy.RUNTIME) // The annotation will exist in the class bytecode file and can be obtained through reflection at runtime.
Annotation class:
@Retention(RetentionPolicy.RUNTIME) // The annotation will exist in the class bytecode file. @Target({ElementType.FIELD,ElementType.METHOD} can be obtained through reflection at runtime//Define the target of the annotation**The range of the field and the enumeration constant/method @Documented//Indicate that the annotation will be included in the javadoc public @interface FieldMeta {/** * Is it a serial number* @return */boolean id() default false;/** * Field name* @return */String name() default "";/** * Is it editable* @return */boolean editable() default true;/** * Whether to display in the list* @return */boolean summary() default true;/** * Field description* @return */String description() default "";/** * Sort fields* @return */int order() default 0;} Entity Class:
public class Anno {@FieldMeta(id=true,name="serial number",order=1)private int id;@FieldMeta(name="name",order=3)private String name;@FieldMeta(name="age",order=2)private int age;@FieldMeta(description="Description",order=4)public String desc(){return "test of java reflection to obtain annotation";}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}} Get the help class for annotation:
public class SortableField {public SortableField(){}public SortableField(FieldMeta meta, Field field) {super();this.meta = meta;this.field = field;this.name=field.getName();this.type=field.getType();}public SortableField(FieldMeta meta, String name, Class<?> type) {super();this.meta = meta;this.name = name;this.type = type;}private FieldMeta meta;private Field field;private String name;private Class<?> type;public FieldMeta getMeta() {return meta;}public void setMeta(FieldMeta meta) {this.meta = meta;}public Field getField() {return field;}public void setField(Field field) {this.field = field;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Class<?> getType() {return type;}public void setType(Class<?> type) {this.type = type;}} To get annotations at runtime, first create a base class:
public class Parent<T> {private Class<T> entity;public Parent() {init();}@SuppressWarnings("unchecked")public List<SortableField> init(){List<SortableField> list = new ArrayList<SortableField>();/**getClass().getGenericSuperclass() returns the Type (type in the Class<T> generic) representing the entity represented by this Class (class, interface, primitive type, or void) *, and then converts it to ParameterizedType. . * getActualTypeArguments() returns an array of Type objects representing the actual type parameters of this type. * [0] is the first one in this array. . * In short, it is to get the actual type of generic parameters of the superclass. . */entity = (Class<T>)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];//FieldMeta filed = entity.getAnnotation(FieldMeta.class);if(this.entity!=null){/**Return all fields in the class, including public, protected, default (package) access and private fields, but do not include inherited fields* entity.getFields(); only returns all accessible public fields of the class or interface represented by the object* In the class getDeclared**() method returns fields, methods, etc. with all access permissions; * See API * */Field[] fields = entity.getDeclaredFields();//for(Field f : fields){//get the annotation containing fieldMeta FieldMeta meta = f.getAnnotation(FieldMeta.class);if(meta!=null){SortableField sf = new SortableField(meta, f);list.add(sf);}}//Return all accessible public methods of the class or interface represented by the object Method[] methods = entity.getMethods(); for(Method m:methods){FieldMeta meta = m.getAnnotation(FieldMeta.class);if(meta!=null){SortableField sf = new SortableField(meta,m.getName(),m.getReturnType());list.add(sf);}}//This method is to create a new FieldSortCom class to implement the Comparator interface to override the compare method to implement sorting//Collections.sort(list, new FieldSortCom());Collections.sort(list, new Comparator<SortableField>() {@Overridepublic int compare(SortableField s1,SortableField s2) {return s1.getMeta().order()-s2.getMeta().order();//return s1.getName().compareTo(s2.getName());//You can also use compare for comparison}});}return list;}} Create a subclass to inherit the base class:
public class Child extends Parent<Anno>{} Test class:
public class TestAnnotation {@SuppressWarnings({ "unchecked", "rawtypes" })public static void main(String[] args) {Parent c = new Child();List<SortableField> list = c.init();//Get the annotation in the class in the generics//Output result for(SortableField l: list){System.out.println("field name: "+l.getName()+"/t Field type: "+l.getType()+"/t Annotation name: "+l.getMeta().name()+"/t Annotation description: "+l.getMeta().description());}}}///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1. The working principle of Annotation:
JDK5.0 provides annotation functionality, allowing developers to define and use their own annotation types. This function consists of a syntax that defines annotation type and a syntax that describes annotation declaration, an API that reads annotation, a class file that uses annotation to modify, and annotation processing tool.
Annotation does not directly affect the semantics of the code, but it can be regarded as a program's tool or class library. It will in turn have some effect on the running program semantics.
Annotation can be read in various ways through a reflection mechanism during runtime.
2. @Override annotation:
java.lang
Comment type Override
@Target(value=METHOD)
@Retention(value=SOURCE)
public @interface Override means that a method declaration intends to override another method declaration in the superclass. If the method annotates with this annotation type but does not override the superclass method, the compiler generates an error message.
The @Override annotation means that the subclass needs to override the corresponding method of the parent class.
Override is a Marker annotation used to identify the Annotation. The Annotation name itself represents the information to be given to the tool program.
Here is an example using @Override annotation:
class A { private String id; A(String id){ this.id = id; } @Override public String toString() { return id; }}3. @Deprecated annotation:
java.lang
Comment type Deprecated
@Documented
@Retention(value=RUNTIME)
public @interface Deprecated program elements annotated with @Deprecated, programmers are discouraged from using such elements, usually because it is dangerous or there are better options. The compiler warns when using unapproved program elements or performing rewrites in unapproved code.
@Deprecated annotation representation method is not recommended.
Deprecated is a Marker annotation.
Here is an example using @Deprecated annotation:
class A { private String id; A(String id){ this.id = id; } @Deprecated public void execute(){ System.out.println(id); } public static void main(String[] args) { A a = new A("a123"); a.execute(); }}4. @SuppressWarnings annotation:
java.lang
Comment TypeSuppressWarnings
@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
@Retention(value=SOURCE)
public @interface SuppressWarnings indicates that the specified compiler warning should be undisplayed in the comment element (and all program elements contained in that comment element). Note that the set of warnings that are undisplayed in a given element is a superset of all warnings that are undisplayed in the element. For example, if you comment a class to unshow a warning and annotate a method to unshow another warning, both warnings will be unshowed in this method.
Depending on the style, programmers should always use this annotation on the innermost nested elements, and it will only work if used there. If you want to unshow a warning in a specific method, you should comment the method instead of its class.
@SuppressWarnings annotation indicates suppression warning.
Here is an example using @SuppressWarnings annotation:
@SuppressWarnings("unchecked")public static void main(String[] args) { List list = new ArrayList(); list.add("abc");}5. Custom annotations:
When using @interface to custom annotations, the java.lang.annotation.Annotation interface is automatically inherited, and other details are automatically completed by the compiler. When defining annotations, other annotations or interfaces cannot be inherited.
Customize the easiest comment:
public @interface MyAnnotation {}Use custom annotation: public class AnnotationTest2 { @MyAnnotation public void execute(){ System.out.println("method"); }} 5.1. Add variables:
public @interface MyAnnotation { String value1();}Use custom annotations: public class AnnotationTest2 { @MyAnnotation(value1="abc") public void execute(){ System.out.println("method"); }}When the attribute name used in the annotation is value, the attribute value interface can be written directly without specifying the name of the attribute when assigning it; except for the unexpected variable names of value, all variable names need to be assigned using name=value.
5.2. Add default values:
public @interface MyAnnotation { String value1() default "abc";}5.3. Multivariate usage enumeration:
public @interface MyAnnotation { String value1() default "abc"; MyEnum value2() default MyEnum.Sunny;}enum MyEnum{ Sunny,Rainy} Use custom annotations:
public class AnnotationTest2 { @MyAnnotation(value1="a", value2=MyEnum.Sunny) public void execute(){ System.out.println("method"); }} 5.4. Array variables:
public @interface MyAnnotation { String[] value1() default "abc";} Use custom annotations:
public class AnnotationTest2 { @MyAnnotation(value1={"a","b"}) public void execute(){ System.out.println("method"); }}6. Set the scope of the annotation:
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Retention indicates how long the annotation of the annotation type should be retained. If a Retention annotation does not exist in the comment type declaration, the retention policy defaults to RetentionPolicy.CLASS.
Target meta comments are only valid when the meta comment type is directly used for comments. If the meta comment type is used as a member of another comment type, it is invalid.
public enum RetentionPolicy
extends Enum<RetentionPolicy> comments retention policy. Constants for this enum type describe different strategies for keeping comments. They are used with Retention meta comment types to specify how long annotations are retained.
CLASS
The compiler will log comments in the class file, but the VM does not need to keep comments at runtime.
RUNTIME
The compiler will record the comments in the class file, and the VM will retain the comments at runtime, so it can be read reflectively.
SOURCE
Comments to discard the compiler. @Retention annotation can provide annotation retention policy for compilers when defining annotations.
The annotation belonging to the CLASS retention policy is @SuppressWarnings, which will not be stored in the .class file.
6.1. Examples of use in custom annotations:
@Retention(RetentionPolicy.CLASS)public @interface MyAnnotation { String[] value1() default "abc";}7. Example of using reflection to read Annotation information of RUNTIME retention policy:
java.lang.reflect
Interface AnnotatedElement
All known implementation classes:
AccessibleObject, Class, Constructor, Field, Method, Package represents a commented element of the program currently running in this VM. This interface allows reflexive reading of comments. All comments returned by methods in this interface are immutable and serializable. The caller can modify the array returned by the accessor of the assigned array enumerated member; this will not have any effect on the array returned by other callers.
If a method in this interface returns a comment (directly or indirectly) containing an assigned Class member that references a class that is not accessible in this VM, attempting to read the class by calling the method returned by the relevant class on the returned comment will result in a TypeNotPresentException.
isAnnotationPresent
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) Returns true if the comment of the specified type exists on this element, otherwise returns false. This method is mainly designed to facilitate access to tag comments.
parameter:
annotationClass - Class object corresponding to annotation type
return:
Return true if the comment of the specified comment type exists on this object, otherwise false
Throw:
NullPointerException - if the given annotation class is null
Start with the following version:
1.5
getAnnotation
<T extends Annotation> T getAnnotation(Class<T> annotationClass) Returns these comments if there are comments of the specified type of this element, otherwise null is returned.
parameter:
annotationClass - Class object corresponding to annotation type
return:
If the comments of the specified comment type of the element exist on this object, these comments are returned, otherwise null
Throw:
NullPointerException - if the given annotation class is null
Start with the following version:
1.5
getAnnotations
Annotation[] getAnnotations() returns all comments that exist on this element. (If this element is not commented, an array of length zero is returned.) The caller of the method can modify the returned array at will; this will not have any effect on the array returned by other callers.
return:
All comments that exist on this element
Start with the following version:
1.5
getDeclaredAnnotations
Annotation[] getDeclaredAnnotations() returns all comments that exist directly on this element. Unlike other methods in this interface, this method ignores inherited annotations. (If no comment exists directly on this element, an array of length zero is returned.) The caller of the method can modify the returned array at will; this will not have any effect on the array returned by other callers.
return:
All comments that exist directly on this element
Start with the following version:
1.5
Here is an example of using reflection to read Annotation information of the RUNTIME retention policy:
Custom annotations:
@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation { String[] value1() default "abc";} Use custom annotations:
public class AnnotationTest2 { @MyAnnotation(value1={"a","b"}) @Deprecated public void execute(){ System.out.println("method"); }} Read information in the annotation:
public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { AnnotationTest2 annotationTest2 = new AnnotationTest2(); //GetClass Instance of AnnotationTest2Class<AnnotationTest2> c = AnnotationTest2.class; //GetMethodInstance Method Method method = c.getMethod("execute", new Class[]{}); //Determine whether the method contains MyAnnotation annotation if(method.isAnnotationPresent(MyAnnotation.class)){ //Get the MyAnnotation annotation instance of this method MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class); //Execute the method method.invoke(annotationTest2, new Object[]{}); //Get myAnnotation String[] value1 = myAnnotation.value1(); System.out.println(value1[0]); } //Get all annotations on the method Annotation[] annotations = method.getAnnotations(); for(Annotation annotation : annotations){ System.out.println(annotation); }}8. Use of limited annotations:
Limited annotations use @Target.
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Target indicates the type of program elements to which the annotation type applies. If a Target meta comment does not exist in the comment type declaration, the declared type can be used on any program element. If such a meta comment exists, the compiler enforces the specified usage limit. For example, this meta comment indicates that the declaration type is itself, i.e. the meta comment type. It can only be used on comment type declarations:
@Target(ElementType.ANNOTATION_TYPE) public @interface MetaAnnotationType { ... } This meta comment indicates that the declaration type can only be used as member types in complex annotation type declarations. It cannot be used directly in comments:
@Target({}) public @interface MemberType { ... } This is a compile-time error that indicates that an ElementType constant appears more than once in the Target comment. For example, the following meta comments are illegal:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD}) public @interface Bogus { ... }public enum ElementTypeextends Enum<ElementType> program element type. Constants of this enum type provide a simple classification of elements declared in a Java program.
These constants are used with the Target meta comment type to specify under what circumstances it is legal to use the comment type.
ANNOTATION_TYPE
Comment type declaration
CONSTRUCTOR
Constructor method statement
FIELD
Field declaration (including enumeration constants)
LOCAL_VARIABLE
Local variable declaration
METHOD
Method statement
PACKAGE
Package Statement
PARAMETER
Parameter declaration
TYPE
Class, interface (including comment types) or enumeration declaration
Examples of limitations on the use of annotations:
@Target(ElementType.METHOD)public @interface MyAnnotation { String[] value1() default "abc";}9. Add notes to the help document:
To add annotation information to the API file while creating a JavaDoc file, you can use java.lang.annotation.Documented.
Declare the build annotation document in a custom annotation:
@Documentedpublic @interface MyAnnotation { String[] value1() default "abc";} Use custom annotations:
public class AnnotationTest2 { @MyAnnotation(value1={"a","b"}) public void execute(){ System.out.println("method"); }}10. Use inheritance in annotations:
By default, annotations are not inherited into subclasses. You can add java.lang.annotation.Inherited annotation declaration when custom annotations are used.
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Inherited indicates that the annotation type is automatically inherited. If an Inherited meta annotation exists in the comment type declaration and the user querys the comment type in a class declaration, and there is no comment of this type in the class declaration, the comment type will be automatically queryed in the superclass of the class. This process is repeated until this type of comment is found or the top level of the class hierarchy is reached. If no superclass has an annotation of that type, the query will indicate that the current class does not have such an annotation.
Note that if you use annotation type to comment anything other than the class, this meta comment type is invalid. Also note that this meta comment only facilitates inheritance of comments from superclasses; it is invalid for comments to implemented interfaces.
The above article briefly talks about Java custom annotations and the use of reflection to obtain annotations during runtime is all the content I share with you. I hope it can give you a reference and I hope you can support Wulin.com more.