Chapter 20: Comments

Preface

1. Annotations are also called metadata
2. The advent of annotations simplifies some duplicate development and often works with aop
3. Annotations without arguments are called label annotations
4. Cleaner, more readable code for easy expansion
5. and compile-time type checking

1. Meta-Notes

Meta Annotation is responsible for annotating other annotations, usually our custom annotations

annotationRole description
@TargetThe position of annotation function; ElementType parameters include: 1 type: class, enumeration, interface; 2 METHOD; 3 FIELD; 4 CONSTRUCTOR; 3 PACKAGE; 3 PARAMETER: parameter
@RetentionSaved annotation level, RetentionPolicy: SOURCE, CLASS, RUNTIME
@InheritedAllows subclasses to inherit annotations from the parent class, which can obtain annotation object information from the parent class
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface InheritedAnnotation {
    String value() default "==inherited information==";
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
 @interface OneAnnotation {
}

@InheritedAnnotation
class ASuper{}
class AChild extends ASuper{

}

@OneAnnotation
class BSuper{}
class BChild extends BSuper{

}

public class InheritedDemo {
    public static void main(String[] args) {
        ASuper inheritedObj = new AChild();
        System.out.println("Used@Inherited Notes, you can get the parent class" + 
        			Arrays.asList(AChild.class.getAnnotations()));
        System.out.println("Used@Inherited Annotation, you can get the parent annotation object information:" + 
        			AChild.class.getAnnotation(InheritedAnnotation.class).value());
        BSuper childObj = new BChild();
        System.out.println("Common annotations, you can get the parent class" +
        		 Arrays.asList(BChild.class.getAnnotations()));
    }
}

Run result:

Used@Inherited Notes, you can get the parent class[@demo.InheritedAnnotation(value=inherited information)]
Used@Inherited Annotation, you can get the parent annotation object information:==inherited information==
Common annotations, you can get the parent class[]

2. Note Elements

1. Annotation element type

1,All Basic Types(byte/short/int/long/float/double/boolean/char)
2,String
3,Class
4,Enum
5,Annotation(Annotation type to achieve nesting of annotations)
6,Arrays of all types above

No packaging type allowed

Custom Notes:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationElementDemo {
    //Basic Type Element
    int intElement();
    //class type
    Class<?> classElement() default Void.class;
    //String type
    String strElement() default "";
    //Array type
    long[] longElement();
    //Enumeration Type
    ElementType elementRef();
    //Annotation type, inline annotation, inheritance annotation effect
    InnerAnnotation innerAnnotaion() default @InnerAnnotation;
    //Wrapper type error: Invalid type'Integer'for annotation member 
//    Integer integer();  
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface InnerAnnotation{
}

2. Default Value Limit

(1) Actually Java annotations are not related to common modifiers (public, static, void, etc.). Example: @Test test annotations can be freely annotated on any modifier method

public class Testable {
    public static void execute() {
        System.out.println("Executing..");
    }    
    @Test //Annotations are used in public decorated methods
    public void testExecute2() {
        execute();
    }
    @Test//Annotations are used in default modification methods
    void testExecute() {
        execute();
    }
    @Test//Annotations are used on private ly modified methods
    private void testExecute1() {
        execute();
    }
    @Test//Annotations are used in static modification methods
    static void testExecute3() {
        execute();
    }
} ///:~

(2) The element must either set a default value or be provided when used. The default value cannot be null. If you want to bypass this limit, you can set an empty string or a negative number.
(3) Shortcut, comment elements have a value attribute, the only assignment element is that you can set a value directly in parentheses without using the element name = value.

3. Notes do not support inheritance

Annotations are defined much like interfaces, except that extend inheritance cannot be used (it can be resolved using embedded annotation elements) and that annotations can set default values.

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
  boolean primaryKey() default false;
  boolean allowNull() default true;
  boolean unique() default false;
} ///:~

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
  String name() default "";
  Constraints constraints() default @Constraints; //Embedded annotation elements
} ///:~

@Target(ElementType.TYPE) // Applies to classes only
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
  public String name() default "";
} ///:~
public class TableCreator {
  public static void main(String[] args) throws Exception {
    Class<?> cl = Class.forName(className);
      DBTable dbTable = cl.getAnnotation(DBTable.class);
      if(dbTable == null) {
        System.out.println("No DBTable annotations in class " + className);
        continue;
      }
      String tableName = dbTable.name();
      // If the name is empty, use the Class name:
      if(tableName.length() < 1)
        tableName = cl.getName().toUpperCase();
      List<String> columnDefs = new ArrayList<String>();
      for(Field field : cl.getDeclaredFields()) {//Traverse through the current class object All objects contain private
        String columnName = null;
        Annotation[] anns = field.getDeclaredAnnotations();
        if(anns.length < 1)
          continue; // Not a db table column
        if(anns[0] instanceof SQLInteger) {
          SQLInteger sInt = (SQLInteger) anns[0];
          // Use field name if name not specified
          if(sInt.name().length() < 1)
            columnName = field.getName().toUpperCase();
          else
            columnName = sInt.name();
          columnDefs.add(columnName + " INT" + getConstraints(sInt.constraints()));
        }
        if(anns[0] instanceof SQLString) {
          SQLString sString = (SQLString) anns[0];
          // Use field name if name not specified.
          if(sString.name().length() < 1)
            columnName = field.getName().toUpperCase();
          else
            columnName = sString.name();
          columnDefs.add(columnName + " VARCHAR(" + sString.value() + ")" +  getConstraints(sString.constraints()));
        }
        StringBuilder createCommand = new StringBuilder("CREATE TABLE " + tableName + "(");
        for(String columnDef : columnDefs)
          createCommand.append("\n    " + columnDef + ",");
        // Remove trailing comma
        String tableCreate = createCommand.substring(0, createCommand.length() - 1) + ");";
        System.out.println("Table Creation SQL for "+className + " is :\n" + tableCreate);
      }
  }
  private static String getConstraints(Constraints con) {
    String constraints = "";
    if(!con.allowNull())
      constraints += " NOT NULL";
    if(con.primaryKey())
      constraints += " PRIMARY KEY";
    if(con.unique())
      constraints += " UNIQUE";
    return constraints;
  }
} /* Output:
Table Creation SQL for annotations.database.Member is :
CREATE TABLE MEMBER(
    FIRSTNAME VARCHAR(30));
Table Creation SQL for annotations.database.Member is :

4. Notes and Reflections

package, Class, construct, method, filed all implement the AnnotatedElement interface, so you can get annotation information through reflection.
AnnotatedElement has the following methods:

Return valueMethod NameExplain
< T extends Annotation>getAnnotation(Class< T > annotationClass)If there are annotation objects of the specified type for the element, those annotations are returned, otherwise null is returned.
Annotation[]getAnnotations()Returns all annotation objects that exist on this element, including inherited from the parent
booleanisAnnotationPresent(Class<? extends Annotation> annotationClass)Returns true if an annotation of the specified type exists on this element, false otherwise.
Annotation[]getDeclaredAnnotations()Returns all comments that exist directly on this element, note that, excluding comments from the parent class, the caller is free to modify the returned array; this has no effect on the array returned by other callers, or returns an array of length 0
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface InheritedAnnotation1 {
    String value() default "==inherited information==";
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface OneAnnotation1 {
}

@InheritedAnnotation1
class Super {
    private int superPrivate;
    public int superPublic;

    public Super() { }
    //private
    private int superPrivate(){ return 0; }
    //Public
    public int superPublic(){ return 0; }

}

@OneAnnotation1
class Child extends Super{
    private int childPrivate;
    public int childPublic;

    public Child() { }
    //private
    private int childPrivate(){ return 0; }
    //Public
    public int childPublic(){ return 0; }

}
public class AnnotationElementTest {
    public static void main(String[] args) throws Exception {
        Class<?> childClazz = Class.forName("demo.Child");
        Method method = childClazz.getDeclaredMethod("childPrivate", null);
        method.setAccessible(true);
        Object o = childClazz.newInstance();
        System.out.println("Reflection calls private method execution return value:"+method.invoke(o,null));
        System.out.println("==================Obtain Child Member Information=======================");
        System.out.println("child Is it annotated OneAnnotation1: " + childClazz.isAnnotationPresent(OneAnnotation1.class));
        System.out.println("child All notes(Include parent class): " + Arrays.asList(childClazz.getAnnotations()));
        System.out.println("child All of their own notes:" + Arrays.asList(childClazz.getDeclaredAnnotations()));
        System.out.println("child Get the annotation object for the parent class to:" + childClazz.getAnnotation(InheritedAnnotation1.class));
        System.out.println("child Get it by itself method(Contain private): " + Arrays.asList(childClazz.getDeclaredMethods()));
        System.out.println("child Get private method objects:" + childClazz.getDeclaredMethod("childPrivate", null));
        System.out.println("==================adopt Child Get parent class member information=======================");
        System.out.println("child Get the parent public method:" + Arrays.asList(childClazz.getMethods()));
        System.out.println("child Is it annotated InheritedAnnotation1: " + childClazz.isAnnotationPresent(InheritedAnnotation1.class));
    }
}

Run result:

Reflection calls private method execution return value:0
==================Obtain Child Member Information=======================
child Is it annotated OneAnnotation1: true
child All notes(Include parent class): [@demo.InheritedAnnotation1(value===inherited information==), @demo.OneAnnotation1()]
child All of their own notes:[@demo.OneAnnotation1()]
child Get the annotation object for the parent class to:@demo.InheritedAnnotation1(value===inherited information==)
child Get it by itself method(Contain private): [private int demo.Child.childPrivate(), public int demo.Child.childPublic()]
child Get private method objects: private int demo.Child.childPrivate()
==================adopt Child Get parent class member information=======================
child Get the parent public method:[public int demo.Child.childPublic(), public int demo.Super.superPublic(), public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
child Is it annotated InheritedAnnotation1: true

summary

Deep understanding of Java annotation types (@Annotation)

Keywords: Java Spring RESTful

Added by Gary Kambic on Fri, 10 Sep 2021 07:29:46 +0300