注解
注解
- 注解的生命周期有 3 种策略,定义在 RetentionPolicy 枚举中
1)SOURCE:在源文件中有效,被编译器丢弃。
2)CLASS:在编译器生成的字节码文件中有效,但在运行时会被处理类文件的 JVM 丢弃。
3)RUNTIME:在运行时有效。这也是注解生命周期中最常用的一种策略,它允许程序通过反射的方式访问注解,并根据注解的定义执行相应的代码。
package test.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
// JsonField 注解的生命周期是 RUNTIME,也就是运行时有效。
@Retention(RetentionPolicy.RUNTIME)
// JsonField 注解装饰的目标是 FIELD,也就是针对字段的。
@Target(ElementType.FIELD)
// 创建注解需要用到@interface关键字。
@interface JsonField {
// JsonField注解有一个参数,名字为value,类型为String,默认值为一个空字符串
// value允许注解的使用者提供一个无需指定名字的参数
// default允许在一个字段上直接使用@JsonField,而无需指定参数的名和值。
public String value() default "";
}
class Writer {
private int age;
// name上的@JsonField注解提供了显式的字符串值。
@JsonField("writerName")
private String name;
// bookName上的@JsonField注解使用了缺省项。
@JsonField
private String bookName;
public Writer(int age, String name, String bookName) {
this.age = age;
this.name = name;
this.bookName = bookName;
}
@Override
public String toString() {
return "Writer{" +
"age=" + age +
", name='" + name + '\'' +
", bookName='" + bookName + '\'' +
'}';
}
}
class JsonSerializer {
// 序列化对象
public static String serialize(Object object) throws IllegalAccessException {
Class<?> objectClass = object.getClass();
Map<String, String> map = new HashMap<>();
// objectClass.getDeclaredFields()通过反射的方式获取对象声明的所有字段
for (Field field : objectClass.getDeclaredFields()) {
// 将反射对象的可访问性设置为 true,供序列化使用
field.setAccessible(true);
// 判断字段是否装饰了JsonField注解
if (field.isAnnotationPresent(JsonField.class)) {
map.put(getSerializedKey(field), (String) field.get(object));
}
}
return toJsonString(map);
}
private static String getSerializedKey(Field field) {
// 获取字段上注解的值
String annotationValue = field.getAnnotation(JsonField.class).value();
// 如果注解的值是空的,则返回字段名
return annotationValue.isEmpty() ? field.getName() : annotationValue;
}
// 借助Stream流的方式返回格式化后的JSON字符串
private static String toJsonString(Map<String, String> jsonMap) {
String elementsString = jsonMap.entrySet()
.stream()
.map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"")
.collect(Collectors.joining(","));
return "{" + elementsString + "}";
}
}
public class Test {
public static void main(String[] args) throws IllegalAccessException {
Writer writer = new Writer(18, "二狗", "劲椎病康复指南");
// {"bookName":"劲椎病康复指南","writerName":"二狗"}
// age字段没有装饰@JsonField注解,所以没有序列化
// name字段装饰了@JsonField注解,并且显示指定了字符串“writerName”,所以序列化后变成了 writerName。
// bookName字段装饰了@JsonField注解,但没有显式指定值,所以序列化后仍然是 bookName。
System.out.println(JsonSerializer.serialize(writer));
}
}