A brief talk on Java custom annotations and run-time reflection fetching annotations _java

Source: Internet
Author: User
Tags deprecated inheritance reflection

Java Custom Annotations

Java annotations are some of the meta information attached to the code, which is used to parse and use some tools as they compile, run, and function as a description and configuration.

Annotations do not and will not affect the actual logic of the code, only to play a supporting role. Included in the Java.lang.annotation package.

1, meta-annotation

A meta annotation is an annotation of an annotation. including @Retention @Target @Document @Inherited four species.

1.1, @Retention: Define the retention policy of annotations

@Retention (Retentionpolicy.source)  //annotations exist only in the source code, the CLASS bytecode file does not contain
@Retention (retentionpolicy.class)   / /default Retention policy, annotations will exist in the class bytecode file, but cannot be obtained at run time,
@Retention (retentionpolicy.runtime)//annotations will exist in the class bytecode file and can be obtained by reflection at run time

Annotation class:

@Retention (retentionpolicy.runtime)//annotations will exist in the class bytecode file and can be obtained by reflection at run time
({Elementtype.field, Elementtype.method})//Define the action target of the annotation * scope field, enumerated constant/method
@Documented//Description The annotation will be included in Javadoc public
@interface Fieldmeta {

	/**
	 * is serial number
	 * @return * *
	Boolean ID () default false;
	/**
	 * Field name
	 * @return
	/String name () default "";
	/**
	 * is editable
	 * @return
	/boolean editable () default true;
	/**
	 * is displayed in the list
	 * @return
	/Boolean summary () default true;
	/**
	 * Field Description
	 * @return
	/String description () default "";
	/**
	 * Sort field
	 * @return
	/int order () default 0;
}

Entity classes:

public class Anno {

	@FieldMeta (id=true,name= "serial number", order=1)
	private int id;
	@FieldMeta (name= "name", order=3)
	private String name;
	@FieldMeta (name= "ages", order=2)
	private int age;
	
	@FieldMeta (description= "description", order=4) public
	String desc () {return
		"Java Reflection fetch Annotation test";
	}
	
	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 the annotation:

 public class Sortablefield {public Sortablefield () {} public Sortablefield (Fieldmet
		A 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;
	The public void SetType (class<?> type) {this.type = type; }
	
	
}

The

runtime gets the annotation, first creating a base class:

public class Parent<t> {private class<t> entity;
	Public Parent () {init (); @SuppressWarnings ("unchecked") Public list<sortablefield> init () {list<sortablefield> List = new Arrayl
		Ist<sortablefield> (); /**getclass (). Getgenericsuperclass () returns the type (class<t> in the generic type) that represents the direct superclass of the Entity (class, interface, base type, or void) represented by this class.
		 Then convert it to parameterizedtype ...
		 * Getactualtypearguments () returns an array of type objects that represent the actual type parameters of this type.
		 * [0] is the first of the array ... * In short, you get the actual type of the generic parameter of the superclass ... * * entity = (class<t>) ((Parameterizedtype) This.getclass (). Getgenericsuperclass ()). Getactualtypearguments () [
0];
		
		Fieldmeta filed = Entity.getannotation (Fieldmeta.class);
			 if (this.entity!=null) {/** Returns all the fields in the class, including public, protected, default (package) access, and private fields, but does not include inherited fields * Entity.getfields (); Returns all accessible public fields for the class or interface that the object represents
* In class, the getdeclared** () method returns all the fields, methods, etc. of the access rights; * can see API * * * * * field[] fields = Entity.getdeclaredfields (); for (field F:fields) {//Get annotations containing Fieldmeta in the field Fieldmeta meta = F.getannotation (Fieldmeta.class);
					if (meta!=null) {Sortablefield SF = new Sortablefield (meta, f);
				List.add (SF);
			
			}//Returns all accessible public methods method[] methods = Entity.getmethods () for the class or interface represented by the object;
				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 approach is to create a new fieldsortcom class implementation comparator interface to rewrite the Compare method implementation sort//Collections.sort (list, new fieldsortcom ()); Collections.sort (list, new comparator<sortablefield> () {@Override public int compare (Sortablefield S1,sorta Blefield S2) {return S1.getmeta ()-Order ()-s2.getmeta (). order ();//Return S1.getname (). CompareTo (S2.getname ());
		/can be compared with compare}});
		
	} return list; }
}

To 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
		//output result for
		(Sortablefield l:list) in the generic class {
			System.out.println ("Field name: +l.getname () +" \ t field type: "+l.gettype () +
					" \ t Note name: "+l.getmeta (). Name () +" \ t annotation Description: "+ L.getmeta (). Description ());}}}

////////////////////////////////////////////////////////////////////////////////////////////////////////

1, annotation working principle:

The JDK5.0 feature provides annotations that allow developers to define and use their own annotation types. This feature consists of a syntax that defines the annotation type and a syntax for describing an annotation declaration, an API for reading annotations, a class file with annotation modifications, and a annotation processing tool.

annotation does not directly affect the semantics of the code, but he can be viewed as a tool or class library of the program. It will in turn affect the program semantics that are running.

Annotation can be used to flush source files, class files, or read in multiple ways at run time through reflection mechanisms.

2, @Override notes:

Java.lang

Annotation type Override
@Target (Value=method)
@Retention (Value=source)
Public @interface override indicates that a method declaration intends to override another method declaration in a superclass. If the method uses this annotation type for annotations but does not override the superclass method, the compiler generates an error message.

@Override Note represents the corresponding method that subclasses want to override the parent class.

Override is a marker annotation, and the annotation,annotation name used to identify itself represents the information to be given to the tool program.

Here is an example of using the @override annotation:

Class A {
  private String ID;
  A (String id) {
    this.id = ID;
  }
  @Override public
  String toString () {return
    ID;
  }
}

3, @Deprecated notes:

Java.lang
Annotation type deprecated
@Documented
@Retention (Value=runtime)

Public @interface deprecated uses @Deprecated annotated program elements to discourage programmers from using such elements, often because it is dangerous or has a better choice. The compiler issues a warning when using an disapproved program element or executing an override in a code that is not approved.

@Deprecated annotation notation is not recommended for use.

Deprecated is a marker annotation.

Here is an example of using the @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 notes:

Java.lang
Annotation type suppresswarnings
@Target (Value={type,field,method,parameter,constructor,local_variable})
@Retention (Value=source)

Public @interface suppresswarnings indicates that the specified compiler warning should be displayed in the annotation element (and all program elements contained in the annotation element). Note that the set of warnings that is displayed in a given element is a superset of the warnings that are displayed in all containing elements. For example, if you annotate a class to suppress a warning and annotate a method to suppress another warning, both warnings are both displayed in this method.

Depending on the style, the programmer should always use this annotation on the innermost nested element, where it is available. If you want to suppress a warning in a particular method, you should annotate the method instead of annotating its class.

@SuppressWarnings annotations indicate a suppression warning.

Here is an example of using the @suppresswarnings annotation:

@SuppressWarnings ("unchecked") public
static void Main (string[] args) {
  list list = new ArrayList ();
  List.add ("abc");
}

5, Custom annotation:

When you use @interface to customize annotations, the Java.lang.annotation.Annotation interface is automatically inherited and other details are automatically completed by the compiler. When you define annotations, you cannot inherit other annotations or interfaces.

Customize the simplest annotations:

Public @interface myannotation {

}

uses a custom annotation: public

class AnnotationTest2 {

  @MyAnnotation
  public void Execute () {
    System.out.println (' method ');
  }
}

5.1. Add Variable:

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 property value interface can be written directly to the property without specifying the name of the attribute, except that the variable names with the value unexpected need to be assigned in a name=value way.

5.2, add the default value:

Public @interface myannotation {

  String value1 () default ' abc ';
}

5.3. Multivariate Use enumeration:

Public @interface myannotation {

  String value1 () default "ABC";
  MyEnum value2 () default myenum.sunny;
}
Enum myenum{
  Sunny,rainy
}

To use a custom annotation:

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";
}

To use a custom annotation:

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 a comment of the annotation type is to be retained. If the Retention annotation does not exist in the annotation type declaration, the retention policy defaults to Retentionpolicy.class.

The Target meta Comment is valid only if the meta annotation type is used directly for annotations. Invalid if the meta annotation type is used as a member of another annotation type.

public enum Retentionpolicy
Extends enum<retentionpolicy> annotation retention policy. Constants of this enumeration type describe the different policies that preserve annotations. They are used with the Retention meta annotation type to specify how long a comment is retained.

CLASS
The compiler will record the annotations in the class file, but the VM does not need to retain the annotations at run time.

RUNTIME
The compiler will record the annotation in the class file, and the VM will retain the annotation at run time, so it can be read in a reflective way.

SOURCE
the comment that the compiler will discard. @Retention annotations can provide the compiler with a retention policy for annotations when defining annotations.

Annotations that belong to the class retention policy are @suppresswarnings, and the annotation information is not stored in the. class file.

6.1. Use examples in custom annotations:

@Retention (retentionpolicy.class) public
@interface myannotation {

  string[] value1 () default "ABC";

7. Examples of using reflection to read annotation information for runtime retention policies:

Java.lang.reflect

Interface Annotatedelement

All known implementation classes:

AccessibleObject, Class, constructor, Field, method, package represents an annotated element of a program that is currently running in this VM. This interface allows for reflective reading of annotations. All annotations returned by methods in this interface are immutable and serializable. The caller can modify the array returned by the accessor of an assigned array enumeration member, which does not have any effect on the array returned by the other caller.

If the comment returned by the method in this interface (directly or indirectly) contains a Class member that is assigned a value, this member references a class that is not accessible in this VM, and attempts to read the class by invoking the method returned by the related class on the returned annotation results in a Typenotpresentexception.

Isannotationpresent
Boolean isannotationpresent (class<? extends Annotation> Annotationclass) returns True if a comment of the specified type exists on this element, otherwise returns false. This approach is designed primarily to facilitate access to markup annotations.

Parameters:

Annotationclass-Class object corresponding to the annotation type

Return:

Returns true if the annotation of the specified annotation type exists on this object, otherwise it returns false

Thrown:

NullPointerException-If the given annotation class is null

Start with the following version:

1.5

Getannotation
<t extends annotation> T getannotation (class<t> annotationclass) If there is a comment for the specified type of the element, the comments are returned, or null is returned.

Parameters:

Annotationclass-Class object corresponding to the annotation type

Return:

If the annotation for the specified annotation type of the element exists on this object, the comments are returned, otherwise null

Thrown:

NullPointerException-If the given annotation class is null

Start with the following version:

1.5

Getannotations
Annotation[] Getannotations () returns all annotations that exist on this element. (If this element does not have a comment, it returns an array of zero length.) The caller of the method is free to modify the returned array, which does not have any effect on the array returned by the other caller.

Return:

All annotations 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, the method ignores inherited annotations. (if no comment exists directly on this element, an array of zero length is returned.) The caller of the method is free to modify the returned array, which does not have any effect on the array returned by the other caller.

Return:

All comments that exist directly on this element

Start with the following version:

1.5

The following is an example of annotation information that uses reflection to read runtime retention policies:

Custom annotations:

@Retention (retentionpolicy.runtime) public
@interface myannotation {

  string[] value1 () default "ABC";

To use a custom annotation:

public class AnnotationTest2 {

  @MyAnnotation (value1={"A", "B"})
  @Deprecated public
  Void execute () {
    System.out.println ("method");
  }

Read the information in the note:

public static void Main (string[] args) throws SecurityException, Nosuchmethodexception, IllegalArgumentException, Illegalaccessexception, invocationtargetexception {
  AnnotationTest2 annotationTest2 = new AnnotationTest2 ();
  Gets the Class instance of AnnotationTest2
  class<annotationtest2> c = annotationtest2.class;
  Gets the method instance that needs to be handled methods
  = C.getmethod ("Execute", New class[]{});
  Determine if the method contains myannotation annotation
  if (method.isannotationpresent (Myannotation.class)) {
    //Get the Myannotation annotation instance of the 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]);
  Gets all annotations on the method
  annotation[] annotations = Method.getannotations ();
  for (Annotation annotation:annotations) {
    System.out.println (Annotation);
  }
}

8, limit the use of annotations:

Limit annotations using @target.

@Documented
@Retention (Value=runtime)
@Target (Value=annotation_type)

The public @interface target indicates the kind of program element to which the annotation type applies. If the Target element annotation does not exist in the annotation type declaration, the declared type can be used on any program element. If such a meta annotation exists, the compiler enforces the specified usage limit. For example, this meta comment indicates that the declaration type is itself, or is a meta annotation type. It can only be used on annotation type declarations:

@Target (elementtype.annotation_type) public
  @interface Metaannotationtype {
    ...
  }

This meta note indicates that the declaration type can be used only as a member type in a complex annotation type declaration. It cannot be used directly for comments:

@Target ({}) public 
  @interface membertype {
    ...
  }

This is a compile-time error that indicates that a ElementType constant appears more than once in the Target annotation. For example, the following meta annotations are illegal:

@Target ({Elementtype.field, Elementtype.method, Elementtype.field}) public
  @interface Bogus {
    ...
  } public enum ElementType

Extends enum<elementtype> program element type. Constants of this enumeration type provide a simple taxonomy of the elements declared in a Java program.

These constants are used with the Target meta annotation type to specify under what circumstances the annotation type is legal.

Annotation_type
Annotation type declaration
Constructor
Constructing method declarations
FIELD
Field declarations (including enumerated constants)
Local_variable
Local variable declaration
Method
Method declaration
PACKAGE
Package Declaration
PARAMETER
Parameter declaration
TYPE
Class, interface (including annotation type) or enum declaration

Examples of usage limitations for annotations:

@Target (elementtype.method) public
@interface myannotation {

  string[] value1 () default "ABC";

9. Add notes to the Help document:

To add the annotation information to the API file while making the Javadoc file, you can use java.lang.annotation.Documented.

To declare a build note document in a custom note:

@Documented public
@interface myannotation {

  string[] value1 () default "ABC";
}

To use a custom annotation:

public class AnnotationTest2 {

  @MyAnnotation (value1={"A", "B"}) public
  void execute () {
    System.out.println ("method");
  }

10. Use Inheritance in annotations:

Annotations are not inherited into subclasses by default, and you can add java.lang.annotation.Inherited annotation declarations to use inheritance when customizing annotations.

@Documented
@Retention (Value=runtime)
@Target (Value=annotation_type)
Public @interface inherited indicates that the annotation type is automatically inherited. If a inherited element annotation exists in the annotation type declaration and the user queries the annotation type in a class of declarations, and there is no comment of that type in the declaration, the annotation type is automatically queried in the superclass of the class. This process repeats until the annotation of this type is found or the top level (Object) of the class hierarchy is reached. If no superclass has a comment of that type, the query indicates that the current class does not have such a comment.

Note that if you use anything other than the annotation type annotation class, this meta annotation type is invalid. Also note that this meta annotation only contributes to inheriting annotations from superclass, and that annotations to implemented interfaces are not valid.

This article on the Java Custom annotation and run-time by reflection to get the annotation is small to share all the content of everyone, hope to give you a reference, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.