关于网站建设的合同协议书,红豆网桂林论坛,物流网站毕业设计,网络营销公司怎么注册注解是 Java 中非常重要的一部分#xff0c;但经常被忽视也是真的。之所以这么说是因为我们更倾向成为一名注解的使用者而不是创建者。Override 注解用过吧#xff1f;Service 注解用过吧#xff1f;但你知道怎么自定义一个注解吗#xff1f;恐怕你会摇摇头#xff0c;摆摆… 注解是 Java 中非常重要的一部分但经常被忽视也是真的。之所以这么说是因为我们更倾向成为一名注解的使用者而不是创建者。Override 注解用过吧Service 注解用过吧但你知道怎么自定义一个注解吗恐怕你会摇摇头摆摆手不好意思地承认自己的确没有自定义过。01、注解是什么注解Annotation是在 Java 1.5 时引入的概念同 class 和 interface 一样也属于一种类型。注解提供了一系列数据用来装饰程序代码类、方法、字段等但是注解并不是所装饰代码的一部分它对代码的运行效果没有直接影响这句话怎么理解呢由编译器决定该执行哪些操作。来看一段代码我随便写的除了打印到控制台的那句宣传语其他都不重要嘻嘻。public class AutowiredTest {Autowiredprivate String name;public static void main(String[] args) {System.out.println(沉默王二一枚有趣的程序员);}
}
注意到 Autowired 这个注解了吧它本来是为 Spring 容器注入 Bean 的现在被我无情地扔在了成员变量 name 的身上但这段代码所在的项目中并没有启用 Spring意味着 Autowired 注解此时只是一个摆设。我之所以举这个无聊的例子就是为了证明一个观点注解对代码的运行效果没有直接影响明白我的用意了吧02、注解的生命周期注解的生命周期有 3 种策略定义在 RetentionPolicy 枚举中。1SOURCE在源文件中有效被编译器丢弃。2CLASS在编译器生成的字节码文件中有效但在运行时会被处理类文件的 JVM 丢弃。3RUNTIME在运行时有效。这也是注解生命周期中最常用的一种策略它允许程序通过反射的方式访问注解并根据注解的定义执行相应的代码。03、注解装饰的目标注解的目标定义了注解将适用于哪一种级别的 Java 代码上有些注解只适用于方法有些只适用于成员变量有些只适用于类有些则都适用。截止到 Java 9注解的类型一共有 11 种定义在 ElementType 枚举中。1TYPE用于类、接口、注解、枚举2FIELD用于字段类的成员变量或者枚举常量3METHOD用于方法4PARAMETER用于普通方法或者构造方法的参数5CONSTRUCTOR用于构造方法6LOCAL_VARIABLE用于变量7ANNOTATION_TYPE用于注解8PACKAGE用于包9TYPE_PARAMETER用于泛型参数10TYPE_USE用于声明语句、泛型或者强制转换语句中的类型11MODULE用于模块04、开始撸注解说再多都不如撸个注解来得让人心动。撸个什么样的注解呢一个字段注解吧它用来标记对象在序列化成 JSON 的时候要不要包含这个字段。Retention(RetentionPolicy.RUNTIME)
Target(ElementType.FIELD)
public interface JsonField {public String value() default ;
}
1JsonField 注解的生命周期是 RUNTIME也就是运行时有效。2JsonField 注解装饰的目标是 FIELD也就是针对字段的。3创建注解需要用到 interface 关键字。4JsonField 注解有一个参数名字为 value类型为 String默认值为一个空字符串。为什么参数名要为 value 呢有什么特殊的含义吗当然是有的value 允许注解的使用者提供一个无需指定名字的参数。举个例子我们可以在一个字段上使用 JsonField(value 沉默王二)也可以把 value 省略变成 JsonField(沉默王二)。那 default 有什么特殊含义吗当然也是有的它允许我们在一个字段上直接使用 JsonField而无需指定参数的名和值。05、使用注解是骡子是马拉出来遛遛对吧现在 JsonField 注解已经撸好了接下来就到了怎么使用它的环节。假设有一个作者类他有 3 个字段分别是 age、name 和 bookName后 2 个是必须序列化的字段。public class Writer {private int age;JsonField(writerName)private String name;JsonFieldprivate String bookName;public Writer(int age, String name, String bookName) {this.age age;this.name name;this.bookName bookName;}// getter / setterOverridepublic String toString() {return Writer{ age age , name name \ , bookName bookName \ };}
}
1name 上的 JsonField 注解提供了显式的字符串值。2bookName 上的 JsonField 注解使用了缺省项。接下来我们来编写序列化类 JsonSerializer内容如下public class JsonSerializer {public static String serialize(Object object) throws IllegalAccessException {Class? objectClass object.getClass();MapString, 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(MapString, String jsonMap) {String elementsString jsonMap.entrySet().stream().map(entry - \ entry.getKey() \:\ entry.getValue() \).collect(Collectors.joining(,));return { elementsString };}
}
JsonSerializer 类的内容看起来似乎有点多但不要怕我一点点来解释直到你搞明白为止。1serialize() 方法是用来序列化对象的它接收一个 Object 类型的参数。objectClass.getDeclaredFields() 通过反射的方式获取对象声明的所有字段然后进行 for 循环遍历。在 for 循环中先通过 field.setAccessible(true) 将反射对象的可访问性设置为 true供序列化使用如果没有这个步骤的话private 字段是无法获取的会抛出 IllegalAccessException 异常再通过 isAnnotationPresent() 判断字段是否装饰了 JsonField 注解如果是的话调用 getSerializedKey() 方法以及获取该对象上由此字段表示的值并放入 jsonElements 中。2getSerializedKey() 方法用来获取字段上注解的值如果注解的值是空的则返回字段名。3toJsonString() 方法借助 Stream 流的方式返回格式化后的 JSON 字符串。如果对 Stream 流比较陌生的话请查阅我之前写的 Stream 流入门。看完我的解释是不是豁然开朗了接下来我们来写一个测试类 JsonFieldTest内容如下public class JsonFieldTest {public static void main(String[] args) throws IllegalAccessException {Writer cmower new Writer(18,沉默王二,Web全栈开发进阶之路);System.out.println(JsonSerializer.serialize(cmower));}
}
程序输出结果如下{bookName:Web全栈开发进阶之路,writerName:沉默王二}
从结果上来看1Writer 类的 age 字段没有装饰 JsonField 注解所以没有序列化。2Writer 类的 name 字段装饰了 JsonField 注解并且显示指定了字符串“writerName”所以序列化后变成了 writerName。3Writer 类的 bookName 字段装饰了 JsonField 注解但没有显式指定值所以序列化后仍然是 bookName。06、鸣谢好了我亲爱的读者朋友以上就是本文的全部内容了是不是感觉撸个注解也没什么难的你也赶紧动动小手试试吧ENDIDEA 终于支持中文版和 JDK 直接下载了太方便了附新版介绍视频6大分布式定时任务对比除了负载均衡Nginx 还能干啥