您当前的位置: 首页 >  Java

java持续实践

暂无认证

  • 1浏览

    0关注

    746博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

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

java持续实践 发布时间:2021-02-21 15:33:32 ,浏览量:1

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

一.自定义注解的格式

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

注解属性支持的类型

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

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

二.自定义注解demo

自定义一个人的描述注解

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

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

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

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

package demo.annotation;

/**
 * 类名称:MyCourse
 *
 * @author: https://javaweixin6.blog.csdn.net/
 * 创建时间:2021/2/21 13:49
 * Version 1.0
 */
@CourseInfoAnnotation(courseName = "Java注解学习", courseTag = "注解", courseProfile = "零基础学习注解开发")
public class MyCourse {

    @PersonInfoAnnotation(name = "周杰伦写代码", language = {"java", "javaScript"})
    private String author;

    @CourseInfoAnnotation(courseName = "java多线程学习", courseTag = "多线程", courseProfile = "从0开始学多线程", courseIndex = 666)
    public void getCourseInfo(){

    }
}

运行上面类中的getCourseInfo方法

public class AnnotationDemo {

    public static void main(String[] args) {
        MyCourse myCourse = new MyCourse();
        myCourse.getCourseInfo();
        System.out.println("执行完成");
    }

}

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

三. 注解与类的关系

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

四. 解析注解的信息 4.1 解析注解在类的信息

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

public class AnnotationParser {
    public static final String enterStr = "\n";

    // 解析类上的注解信息
    public static void parseTypeAnnotation() {
        Class clazz = MyCourse.class;
        // 获取类上的注解信息
        Annotation[] annotations = clazz.getAnnotations();
        // 遍历上的所有的注解
        for (Annotation annotation : annotations) {
            // 注解进行强制类型转换
            CourseInfoAnnotation courseInfoAnnotation = (CourseInfoAnnotation) annotation;
            // 逐一获取注解的相关信息
            System.out.println("课程名: " + courseInfoAnnotation.courseName() + enterStr +
                    "课程标签: " + courseInfoAnnotation.courseTag() + enterStr +
                    "课程简介: " + courseInfoAnnotation.courseProfile() + enterStr +
                    "课程序号: " + courseInfoAnnotation.courseIndex());
        }
    }

    public static void main(String[] args) {
        parseTypeAnnotation();
    }
}

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

4.2 解析注解在成员变量上的信息
   public static final String enterStr = "\n";
  
  // 解析成员变量上的注解信息
    public static void parseFieldAnnotation() {
        Class clazz = MyCourse.class;
        // 获取所有的成员变量
        Field[] fields = clazz.getDeclaredFields();
        // 遍历所有的成员变量
        for (Field field : fields) {
            // 判断成员变量中是否有指定类型的注解
            boolean isAnnotationPresent = field.isAnnotationPresent(PersonInfoAnnotation.class);
            if (isAnnotationPresent) {
                PersonInfoAnnotation personInfoAnnotation = field.getAnnotation(PersonInfoAnnotation.class);
                System.out.println("名字: " + personInfoAnnotation.name() + enterStr +
                        "年龄:  " + personInfoAnnotation.age() + enterStr +
                        "性别: " + personInfoAnnotation.gender() + enterStr);

                String[] languages = personInfoAnnotation.language();
                for (String language : languages) {
                    System.out.println("课程名: " + language);
                }
            }
        }
    }
public static void main(String[] args) {
        parseFieldAnnotation();
    }

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

4.3 解析注解在方法上的信息
    public static final String enterStr = "\n";
   // 解析方法上的注解信息
    public static void parseMethodAnnotation() {
        Class clazz = MyCourse.class;
        // 获取所有的方法
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {

            boolean isAnnotationPresent = method.isAnnotationPresent(CourseInfoAnnotation.class);
            // 判断是否有特定的注解
            if (isAnnotationPresent) {
                //强制转换为特定的注解
                CourseInfoAnnotation courseInfoAnnotation = method.getAnnotation(CourseInfoAnnotation.class);
                System.out.println("课程名: "+courseInfoAnnotation.courseName()+enterStr+
                        "课程标签: "+courseInfoAnnotation.courseTag()+enterStr+
                        "课程简介: "+courseInfoAnnotation.courseProfile()+enterStr+
                        "课程序号: "+courseInfoAnnotation.courseIndex()+enterStr);
            }
        }
    }
	public static void main(String[] args) {
        parseMethodAnnotation();
    }

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

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

关注
打赏
1658054974
查看更多评论
立即登录/注册

微信扫码登录

0.0984s