Detailed introduction to the basics of java annotations
Preface
Annotations are a very popular addition introduced by Java, providing a new avenue of structured and type checking capabilities, allowing programmers to add metadata to their code without causing the code to be cluttered and difficult to read. Using annotations can help us avoid writing cumbersome deployment description files, as well as other generated files.
The syntax of annotation is relatively simple. In addition to the use of @ symbols, it is basically consistent with the inherent syntax of Java. However, since there are few built-in annotations provided in the java source code, most students do not know much about annotations. Although we have all come into contact with several built-in annotations in java:
@Override,Indicates that the current method definition will override the method in the superclass。 @Deprecated,Indicates that the current method is about to be abandoned,Not recommended。 @SuppressWarnings,Warning message indicating that the compiler is ignored。
But this does not allow us to experience the power and convenience of annotations. In fact, Java also provides four other annotations, which are specifically responsible for the creation of new annotations. Today we will learn how to create and use annotations.
Definition of annotation class
First, let’s take a look at the definition of an annotation class:
@Target() @Retention() public @interface Constraints { boolean primaryKey() default false; boolean allowNull() default true; boolean unique() default false; }
Except for the @ symbol, the definition of an annotation class is very similar to an empty interface. When defining annotations, some meta annotations are needed, such as @Target and @Retention. Java provides four kinds of meta annotations, and the definition is as follows:
@Target: Indicates where this annotation can be used.
The value (ElementType) includes:
CONSTRUCTOR: used to describe the constructor
FIELD: used to describe the domain
LOCAL_VARIABLE: used to describe local variables
METHOD: used to describe the method
PACKAGE: used to describe packages
PARAMETER: used to describe parameters
TYPE: used to describe classes, interfaces (including annotation types) or enum declarations
@Retention: At what level does this annotation information need to be saved.
RetentionPolicy includes:
SOURCE: Valid in source files (i.e., source files are retained)
CLASS: Valid in class file (i.e. class reserved)
RUNTIME: Valid at runtime (i.e., reserved at runtime), so the annotation information can be read through the reflection mechanism.
@Documented: means that this annotation is included in javadoc.
@Inherited: Indicates that subclasses are allowed to inherit annotations from parent classes.
It can be seen that the definition annotation format is:
public @interface annotation name {definition body}
The elements defined in the annotation class are called annotation elements. The types available for annotation elements are as follows:
All basic data types(int,float,boolean,byte,double,char,long,short) Stringtype Classtype enumtype Annotationtype 以上所有type的数组
If you use other types, the compiler will report an error. Note that no packaging type is allowed, but due to the existence of automatic packaging, this is not a limitation. Annotations can also be used as elements, for example, we define an annotation class:
@Target() @Retention() public @interface SQLString { int value() default 0; String name() default ""; Constraints constraints() default @Constraints; //There is no bracket after @Constraints to indicate that the default value is used. You can add brackets and define the initial value in it, such as @Constraints(unique=true)}
It can be seen that all annotation elements have a default value. The compiler is a bit too picky about the default values of elements. First, the elements must have default values; second, null cannot be used as the default values. So we can only define some special values ourselves, such as empty strings or negative numbers, to indicate that an element does not exist.
Use of annotation classes
The annotation class is defined, how to use it?
In order to reflect the convenience and power of annotations, we write a demo here, using annotations to automatically generate an SQL command to build a database table.
In addition, we provide two annotation classes:
@Target() @Retention() public @interface DBTable { public String name() default ""; }
@Target() @Retention() public @interface SQLInteger { String name() default ""; Constraints constraints() default @Constraints; }
OK, now we have 4 annotation classes in total.
@DBTable represents the database table, and the annotated element name represents the table name;
@Constraints represents the conditional supplement to each column of the data table. There is whether primaryKey is the primary key, default false, allowNull is allowed to be empty, default true, unique data is unique, default false;
@SQLString represents the String column in the table, the annotation element value represents the column length, the name represents the column name, and the constraints represent some constraints on the column;
@SQLInteger represents the int column in the table, name represents the column name, and constraints represents some constraints on the column;
Below we define a simple Bean class, where the above 4 annotation classes are applied:
@DBTable(name = "MEMBER") public class Member { @SQLString(30) String firstName; @SQLString(50) String lastName; @SQLInteger int age; @SQLString(value = 30, constraints = @Constraints(primaryKey = true)) String handle; public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public int getAge() { return age; } public String getHandle() { return handle; } public String toString() { return handle; } }
When used, the annotated element is represented as a name-value pair and needs to be placed in brackets after the @ annotated class name declaration. If no brackets are used, it means that the default values are used all.
1. Class annotation @DBTable gives the value MEMBER, which will be used as the name of the table;
2. The properties of beans firstName and lastName are both annotated as @SQLString type. There are two interesting things about these annotations: first, they both use the default values of the embedded @Constraints annotation; second, they both use shortcuts. What is a shortcut? If an element named value is defined in the programmer's annotation, and when applying the annotation, if the element is the only element that needs to be assigned, then there is no need to use the syntax of the name-value pair, but just give the value required by the value element in parentheses. This can be applied to any legal type of elements. Of course, this also limits the programmer to name this element value.
The default value of all Bean attributes ages is used, and handle is the primary key.
3. All Bean attribute ages use the default value, and handle is the primary key.
Implement annotation processor
When the annotation class is in use, we also need an annotation processor to parse the beans we defined so that the annotation can be converted into the operations we need.
The following defines the annotation processor that parses the bean. Our goal is to output a SQL statement. Reflection technology is mainly used.
public class TableCreator { public static void main(String[] args) throws Exception{ //Pause the Bean class name we defined and bring the package nameClass<?> cl = (""); //Check whether the class we passed in has @DBTable annotation DBTable dbTable = (); List<String> columnDefs = new ArrayList<String>(); //Get all defined properties in the class for(Field filed : ()){ String columnName = null; //Get the annotation of the attribute, multiple annotations can be used for a target Annotation[] anns = (); if( < 1){ continue; } //SQLString annotation is walking if(anns[0] instanceof SQLString){ SQLString sString = (SQLString)anns[0]; //name() uses the default value, so the attribute name is taken here if(().length() < 1){ columnName = ().toUpperCase(); }else{ columnName = (); } //Construct SQL statement (columnName + " VARCHAR(" + () + ")" + getConstraints(())); } //SQLInteger annotation is walking if(anns[0] instanceof SQLInteger){ SQLInteger sInt = (SQLInteger)anns[0]; if(().length() < 1){ columnName = ().toUpperCase(); }else{ columnName = (); } (columnName + " INT" + getConstraints(())); } } StringBuilder creator = new StringBuilder("CREATE TABLE " + () + "( "); for(String c : columnDefs){ ("\n" + c + ","); } (()-1); (")"); (()); } private static String getConstraints(Constraints con) { String constraints = ""; if(!()){ constraints += " NOT NULL"; } if(()){ constraints += " PRIMARY KEY"; } if(()){ constraints += " UNIQUE"; } return constraints; } }
The final output:
CREATE TABLE MEMBER( FIRSTNAME VARCHAR(30), LASTNAME VARCHAR(50), AGE INT, HANDLE VARCHAR(30) PRIMARY KEY)
Summarize
Finally, through this article, we need to learn a few points:
1. Understand the explanation and use of 4 kinds of Java meta annotations;
2. Can customize the annotation class;
3. Understand the definition and rules of annotated elements;
4. Can use annotation classes;
5. Be able to write a simple annotation processor to parse annotations.
If you have any questions, please leave a message or go to the community of this site to exchange and discuss. Thank you for reading. I hope it can help you. Thank you for your support for this site!