A comment

A comment

​ Annotations are a very important part of Java. We use them all the time, especially when developing with the Spring framework. But how to customize an annotation, or how does an annotation take effect, and what is its working principle? Next, let’s make a comment together

What is the annotation

​ Annotation is a concept introduced in Java 1.5 and belongs to a type. Annotations provide a series of data to modify the program code (classes, methods, fields), but the annotation is not part of the modified code, that is, it has no direct impact on the operation of the code, and the compiler determines which operations to perform

Annotation life cycle

​ There are three strategies for the life cycle of annotations, which are defined in the RetentionPolicy enumeration

  • SOURCE: valid in the source file and discarded by the compiler
  • CLASS: valid in the bytecode file generated by the compiler, but will be discarded by the JVM that processes the class file at runtime
  • RUNTIME: Valid at runtime. This is also the most commonly used strategy in the annotation life cycle, which allows continuous access to annotations through reflection, and executes the corresponding code according to the definition of the annotation

The goal of annotation modification

​ The goal of the annotation defines which level of Java code the annotation will be applied to. Some annotations are only applicable to methods.

​ The types of annotations in 11 are defined in ElementType

  • TYPR: used for classes, interfaces, annotations, enumerations
  • FIELD: Used for fields (member variables of the class), or enum constants
  • METHOD: Used for methods
  • PARAMETER: used for parameters of ordinary methods or construction methods
  • CONSTRUCTOR: used to construct the method
  • LOCAL_VARIABLE: used for variables
  • ANNOTATION_TYPE: used for annotation
  • PACKAGE: used for packages
  • TYPE_PARAMETER: used for generic parameters
  • TYPE_USE: used to declare the type in the statement, generic or cast statement
  • MODULE: for modules

Start commenting

​ Let’s mark a field’s annotation to mark whether the object should contain this field when it is serialized into JSON

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JsonField {
    
    
    public String value() default "";
}
  • Explanation:

    • The life cycle of JsonField annotation is RUNTIME, which is valid at runtime
    • The goal of JsonField annotation modification is FIELD, which is for the field
    • @Interface keyword is needed to create annotation
    • JsonField annotation has only one parameter, the name is value, the type is String, and the default value is an empty string

    The parameter name is value, allowing the user of the annotation to provide a parameter without specifying a name. That is, we can use @JsonField (value="塚狐") on a field, or omit value= to become @JsonField ("塚狐")

    • default "" allows us to directly use @JsonField on a field without specifying the name and value of the parameter

Use annotations

​ Create a class, containing three fields: age, name, address, the last two are required serialized fields

public class People {
    
    
    private  int age ;

    @JsonField("writeName")
    private String name;

    @JsonField
    private String address;

    public People(int age,String name,String address){
    
    
        this.age=age;
        this.name=name;
        this.address=address;
    }

    @Override
    public String toString() {
    
    
        return "People{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

among them:

  • The @JsonField annotation on the name provides the displayed string value
  • The @JsonField annotation on address uses the default value

Next we write the serialization class JsonSerializer:

public class JsonSerializer {
    
    
    public static String serialize(Object object) throws IllegalAccessException {
    
    
        Class<?> objectClass = object.getClass();
        Map<String, String> jsonElements = new HashMap<>();
        for (Field field : objectClass.getDeclaredFields()) {
    
    
            field.setAccessible(true);
            if (field.isAnnotationPresent(JsonField.class)) {
    
    
                jsonElements.put(getSerializedKey(field), (String) field.get(object));
            }
        }
        return toJsonString(jsonElements);
    }

    private static String getSerializedKey(Field field) {
    
    
        String annotationValue = field.getAnnotation(JsonField.class).value();
        if (annotationValue.isEmpty()) {
    
    
            return field.getName();
        } else {
    
    
            return annotationValue;
        }
    }

    private static String toJsonString(Map<String, String> jsonMap) {
    
    
        String elementsString = jsonMap.entrySet()
                .stream()
                .map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"")
                .collect(Collectors.joining(","));
        return "{" + elementsString + "}";
    }
}

Let's take a look at their respective meanings and functions:

  • serialize()The method is used to serialize an object, and it receives a parameter of type Object. objectClass.getDeclaredFields()Get all the fields declared by the object by reflection, and then traverse the for loop. In a for loop, first by field.setAccessible(true)the reflecting object accessibility set to true, for the sequence of use (without this step, then, private field can not be obtained, throws IllegalAccessException exception); again by isAnnotationPresent()determining whether the field decorated JsonFieldannotation, and if so, calls the getSerializedKey()method, and thus obtain the value field indicates the object, and placed in jsonElements.
  • getSerializedKey() The method is used to get the value of the annotation on the field. If the value of the annotation is empty, the field name is returned.
  • toJsonString() The method returns the formatted JSON string with the help of Stream.

Test notes

public class JsonFileTest {
    
    
    public static void main(String[] args) throws IllegalAccessException{
    
    
        People cmower = new People(18,"冢狐","中国");
        System.out.println(JsonSerializer.serialize(cmower));
    }
}
  • result:

{"WriteName":"Mound Fox","address":"China"}

  • analysis
    • First, the age field is not annotated by @JsonField so it is not serialized
    • The name modifies the @JsonField annotation and shows that the string writerName is specified, so it becomes writeName after serialization
    • The address field is decorated with the @JsonField annotation, but the specified value is not displayed, so it is still address after serialization

At last

  • If you feel that you are rewarded after reading, I hope to give me a thumbs up. This will be my biggest motivation for updating. Thank you for your support.
  • Welcome everyone to pay attention to my official account [java Toka Fox], focus on the basic knowledge of java and computer, and ensure that you will get something after reading it. If you don’t believe me, hit me
  • If you have different opinions or suggestions after reading, welcome to comment and share. Thank you for your support and love.

Guess you like

Origin blog.csdn.net/issunmingzhi/article/details/108262149