Java 自定义注解的实现与解析注解信息

Love The Way You Lie 2022-10-31 04:15 369阅读 0赞

文章目录

      • 一.自定义注解的格式
      • 二.自定义注解demo
      • 三. 注解与类的关系
      • 四. 解析注解的信息
        • 4.1 解析注解在类的信息
        • 4.2 解析注解在成员变量上的信息
        • 4.3 解析注解在方法上的信息

一.自定义注解的格式

注解由于都是给其他的类中使用的, 所以一般都定义为public

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzMjI5NjY5_size_16_color_FFFFFF_t_70
注解属性支持的类型

  • 所有的基本数据类型 8个
  • String类型
  • Class类型
  • Enum 类型
  • Annotation类型
  • 以上所有类型的数据

注解是不能直接去继承其他的注解的.

二.自定义注解demo

自定义一个人的描述注解

  1. // 该注解作用于成员变量上
  2. @Target(ElementType.FIELD)
  3. // 该注解的生命周期是运行时, 可以通过反射获取信息
  4. @Retention(RetentionPolicy.RUNTIME)
  5. public @interface PersonInfoAnnotation {
  6. // 名字
  7. public String name();
  8. public int age() default 19;
  9. public String gender() default "男";
  10. // 开发语言
  11. public String[] language();
  12. }

自定义一个课程信息描述的注解

  1. // 该注解作用于类和方法上
  2. @Target({ ElementType.TYPE, ElementType.METHOD})
  3. // 该注解的生命周期是运行时, 可以通过反射获取信息
  4. @Retention(RetentionPolicy.RUNTIME)
  5. public @interface CourseInfoAnnotation {
  6. // 课程名称
  7. public String courseName();
  8. // 课程标签
  9. public String courseTag();
  10. // 课程简介
  11. public String courseProfile();
  12. // 课程序号
  13. public int courseIndex() default 101;
  14. }

定义一个课程的类MyCourse, 用注解来描述其相关信息

  1. package demo.annotation;
  2. /** * 类名称:MyCourse * * @author: https://javaweixin6.blog.csdn.net/ * 创建时间:2021/2/21 13:49 * Version 1.0 */
  3. @CourseInfoAnnotation(courseName = "Java注解学习", courseTag = "注解", courseProfile = "零基础学习注解开发")
  4. public class MyCourse {
  5. @PersonInfoAnnotation(name = "周杰伦写代码", language = { "java", "javaScript"})
  6. private String author;
  7. @CourseInfoAnnotation(courseName = "java多线程学习", courseTag = "多线程", courseProfile = "从0开始学多线程", courseIndex = 666)
  8. public void getCourseInfo(){
  9. }
  10. }

运行上面类中的getCourseInfo方法

  1. public class AnnotationDemo {
  2. public static void main(String[] args) {
  3. MyCourse myCourse = new MyCourse();
  4. myCourse.getCourseInfo();
  5. System.out.println("执行完成");
  6. }
  7. }

执行结果如下, 可以看到注解没有影响其Java类的相关代码执行.
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzMjI5NjY5_size_16_color_FFFFFF_t_70 1

三. 注解与类的关系

下图可以看到Class 类实现了AnnotatedElement接口. AnnotatedElement接口是与注解相关的接口.
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzMjI5NjY5_size_16_color_FFFFFF_t_70 2
通过如下的类图可以看到AnnotatedElement是顶级接口, 与反射相关的Class , Field. Method , Constructor 其本质都实现了AnnotatedElement接口
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzMjI5NjY5_size_16_color_FFFFFF_t_70 3
此接口常用的方法有如下的三个.
getAnnotation(Class<T> annotationClass) 获取某一个注解, 包含继承过来的注解
Annotation[] getAnnotations(); 获取所有的注解, 包含继承过来的
default boolean isAnnotationPresent 用于判断是否包含指定的注解元素, 如果包含返回true, 如果不包含,返回false.
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzMjI5NjY5_size_16_color_FFFFFF_t_70 4

四. 解析注解的信息

4.1 解析注解在类的信息

创建一个AnnotationParser 类, 用于解析注解的信息.
如下的代码 . 解析了上面的步骤中MyCourse类的, 标注在其类上的CourseInfoAnnotation注解的信息.

  1. public class AnnotationParser {
  2. public static final String enterStr = "\n";
  3. // 解析类上的注解信息
  4. public static void parseTypeAnnotation() {
  5. Class<MyCourse> clazz = MyCourse.class;
  6. // 获取类上的注解信息
  7. Annotation[] annotations = clazz.getAnnotations();
  8. // 遍历上的所有的注解
  9. for (Annotation annotation : annotations) {
  10. // 注解进行强制类型转换
  11. CourseInfoAnnotation courseInfoAnnotation = (CourseInfoAnnotation) annotation;
  12. // 逐一获取注解的相关信息
  13. System.out.println("课程名: " + courseInfoAnnotation.courseName() + enterStr +
  14. "课程标签: " + courseInfoAnnotation.courseTag() + enterStr +
  15. "课程简介: " + courseInfoAnnotation.courseProfile() + enterStr +
  16. "课程序号: " + courseInfoAnnotation.courseIndex());
  17. }
  18. }
  19. public static void main(String[] args) {
  20. parseTypeAnnotation();
  21. }
  22. }

打印结果如下, 说明成功解析了在其类上的注解信息 .
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzMjI5NjY5_size_16_color_FFFFFF_t_70 5

4.2 解析注解在成员变量上的信息

  1. public static final String enterStr = "\n";
  2. // 解析成员变量上的注解信息
  3. public static void parseFieldAnnotation() {
  4. Class<MyCourse> clazz = MyCourse.class;
  5. // 获取所有的成员变量
  6. Field[] fields = clazz.getDeclaredFields();
  7. // 遍历所有的成员变量
  8. for (Field field : fields) {
  9. // 判断成员变量中是否有指定类型的注解
  10. boolean isAnnotationPresent = field.isAnnotationPresent(PersonInfoAnnotation.class);
  11. if (isAnnotationPresent) {
  12. PersonInfoAnnotation personInfoAnnotation = field.getAnnotation(PersonInfoAnnotation.class);
  13. System.out.println("名字: " + personInfoAnnotation.name() + enterStr +
  14. "年龄: " + personInfoAnnotation.age() + enterStr +
  15. "性别: " + personInfoAnnotation.gender() + enterStr);
  16. String[] languages = personInfoAnnotation.language();
  17. for (String language : languages) {
  18. System.out.println("课程名: " + language);
  19. }
  20. }
  21. }
  22. }
  23. public static void main(String[] args) {
  24. parseFieldAnnotation();
  25. }

在这里插入图片描述
在这里插入图片描述
通过上面的图片可以看到成功解析了注解在成员变量上的信息. 其中年龄和性别取的默认值.

4.3 解析注解在方法上的信息

  1. public static final String enterStr = "\n";
  2. // 解析方法上的注解信息
  3. public static void parseMethodAnnotation() {
  4. Class<MyCourse> clazz = MyCourse.class;
  5. // 获取所有的方法
  6. Method[] methods = clazz.getDeclaredMethods();
  7. for (Method method : methods) {
  8. boolean isAnnotationPresent = method.isAnnotationPresent(CourseInfoAnnotation.class);
  9. // 判断是否有特定的注解
  10. if (isAnnotationPresent) {
  11. //强制转换为特定的注解
  12. CourseInfoAnnotation courseInfoAnnotation = method.getAnnotation(CourseInfoAnnotation.class);
  13. System.out.println("课程名: "+courseInfoAnnotation.courseName()+enterStr+
  14. "课程标签: "+courseInfoAnnotation.courseTag()+enterStr+
  15. "课程简介: "+courseInfoAnnotation.courseProfile()+enterStr+
  16. "课程序号: "+courseInfoAnnotation.courseIndex()+enterStr);
  17. }
  18. }
  19. }
  20. public static void main(String[] args) {
  21. parseMethodAnnotation();
  22. }

结果打印如下
在这里插入图片描述
通过下图可以看到成功的获取了方法上的注解信息.
20210221151805904.png

当把注解上的Retention从RUNTIME 改为CLASS或SOURCE 时 , 如下图所示
在这里插入图片描述
再次执行上面的获取注解信息的方法 , 结果如下图所示, 获取到的是空白的信息, 因此如果要获取注解中的信息, Retention要使用RUNTIME
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,369人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java实现定义注解

    前言      上一篇文章介绍了注解的一些基本知识,这次来介绍下如何实现自定义注解及注解如何使用。 正文      注解是一种能被添加到java源代码中的元数据,